• JNA 调用操作系统函数 和 系统调用


    linux系统调用syscall 表:https://filippo.io/linux-syscall-table/

    Linux Namespace 特性简要介绍

    原文:https://iliangqunru.bitcron.com/post/2018/jna-shi-ji-kai-fa-zhong-ruo-gan-wen-ti-jie-jue-fang-fa

    其他:

    JNI的替代者—使用JNA访问Java外部功能接口

    Invoke Syscalls from Java

     

    java发起系统调用,本质还是用了JNA,调用OS提供的syacall函数:

    import com.sun.jna.Library;
    import com.sun.jna.Native;
    
    public class Test {
        public interface CStdLib extends Library {
            int syscall(int number, Object... args);
        }
    
        public static void main(String[] args) {
            CStdLib c = (CStdLib)Native.loadLibrary("c", CStdLib.class);
    
            // WARNING: These syscall numbers are for x86 only
            System.out.println("PID: " + c.syscall(20));
            System.out.println("UID: " + c.syscall(24));
            System.out.println("GID: " + c.syscall(47));
            c.syscall(39, "/tmp/create-new-directory-here");
        }
    }

    很早就已经听说过 JNI(Java Native Interface)Java 本地接口,奈何调用本地动态链接库太过于复杂,就一直没有再尝试。而最近因为工作需要调用 Windows DLL 动态链接库(对应 Linux 中 so 文件),而对 JNA 有了入坑体验,对实际工作中遇到的问题做出总结。

    1. 调用 Windows 窗口打印Hello World

    1. pom 依赖
    <dependency>
                <groupId>net.java.dev.jna</groupId>
                <artifactId>jna</artifactId>
                <version>latest</version>
            </dependency>
    
    1. JNA 在加载驱动时提供两种加载方式 , 直接映射 和 接口生成

    接口生成

    public interface HelixcsDll extends StdCallLibrary {
            // loadLibary 为动态链接库加载目录
            HelixcsDll HELIXCS_DLL = Native.loadLibrary("helixcs.dll", HelixcsDll.class);
            // 在 dll 中存在相同 SomeFunction 的函数 
            void SomeFunction(String content);
        }
        
        // 调用
        HelixcsDll.HELIXCS_DLL.SomeFunction("Hello World");
    

    直接映射

    class Helixcs{
            static {
                Native.register("helixcs.dll");
            }
            // 映射为本地方法
            public static  native void SomeFunction(String content);
    
            public static void main(String[] args) {
                SomeFunction("Hello World");
            }
        }

    官方例子:

    package com.sun.jna.examples;
    
    import com.sun.jna.Library;
    import com.sun.jna.Native;
    import com.sun.jna.Platform;
    
    /** Simple example of JNA interface mapping and usage. */
    public class HelloWorld {
    
        // This is the standard, stable way of mapping, which supports extensive
        // customization and mapping of Java to native types.
    
        public interface CLibrary extends Library {
            CLibrary INSTANCE = (CLibrary)
                Native.load((Platform.isWindows() ? "msvcrt" : "c"),
                                    CLibrary.class);
    
            void printf(String format, Object... args);
        }
    
        public static void main(String[] args) {
            CLibrary.INSTANCE.printf("Hello, World
    ");
            for (int i=0;i < args.length;i++) {
                CLibrary.INSTANCE.printf("Argument %d: %s
    ", i, args[i]);
            }
        }
    }

    2. C 类型和 Java 类型映射。

    1. JNA 官方提供的默认类型映射

    Default Type Mappings 默认类型映射

    Java primitive types (and their object equivalents) map directly to the native C type of the same size.

    Java 原始类型以相同的大小映射 C 类型。

    Native Type Size Java Type Common Windows Types
    char 8-bit integer byte BYTE, TCHAR
    short 16-bit integer short WORD
    wchar_t 16/32-bit character char TCHAR
    int 32-bit integer int DWORD
    int boolean value boolean BOOL
    long 32/64-bit integer NativeLong LONG
    long long 64-bit integer long __int64
    float 32-bit FP float  
    double 64-bit FP double  
    char* C string String LPTCSTR
    void* pointer Pointer LPVOID, HANDLE, LPXXX

    未签名类型作为签名类型来映射。 C 中枚举类型可替换为 “int”。

    Unsigned types use the same mappings as signed types. C enums are usually interchangeable with "int".

    3. 官方提供的详细的类型映射

    Marshalling/Unmarshalling (Java/Native Type Conversions)


    C Type Native Representation Java Type
    char 8-bit integer byte
    wchar_t platform-dependent char
    short 16-bit integer short
    int 32-bit integer int
    int boolean flag boolean
    enum enumeration type int (usually)
    long long, __int64 64-bit integer long
    float 32-bit floating point float
    double 64-bit floating point double
    pointer (e.g. void*) platform-dependent (32- or 64-bit pointer to memory) BufferPointer
    pointer (e.g. void*),array 32- or 64-bit pointer to memory (argument/return)contiguous memory (struct member) <P>
    In addition to the above types, which are supported at the native layer, the JNA Java library automatically handles the following types. All but NativeMapped and NativeLong are converted to Pointer before being passed to the native layer.
    long platform-dependent (32- or 64-bit integer) NativeLong
    const char* NUL-terminated array (native encoding or jna.encoding) String
    const wchar_t* NUL-terminated array (unicode) WString
    char NULL-terminated array of C strings String[]
    wchar_t NULL-terminated array of wide C strings WString[]
    void** NULL-terminated array of pointers Pointer[]
    struct*struct pointer to struct (argument or return) (or explicitly)struct by value (member of struct) (or explicitly) Structure
    union same as Structure Union
    struct[] array of structs, contiguous in memory Structure[]
    void (*FP)() function pointer (Java or native) Callback
    pointer (<T> *) same as Pointer PointerType
    other integer type IntegerType
    other custom mapping, depends on definition NativeMapped

    4. 经验总结默认映射关系

    尽管 JNA 官方已经提供了详细的类型映射文档。但在实际中发现按照官方映射可能出现莫名问题。对此我们在实际开发中对于一些类型的映射报错,可以参考以下映射做出调整。

    C类型JNA类型说明
    char * out Pointer Pointer room = new Memory(30);
    uchar * out Pointer Pointer room = new Memory(30);
    long * long [ ]  
    int * init [ ]  
    int int  
    char * byte [ ]  
    char * argv[] String []  
    uchar int  
    long NativeLong 兼容 32和64位

    5. 常见错误

    1. UnsatisfiedLinkError 问题

    存在多个动态链接库之间调用情况,可能缺少其中某一个动态链接库文件。

    2. Error Memory Access 问题

    较大情况下存在参数类型映射错误,参考 JNA 类型映射。

    3. dll can not find in win32/86

    无法加载到动态链接库文件路径,需要将动态链接库放到项目根目录下,推荐开启 JNA 驱动加载 debug 模式,

    System.setProperty("jna.debug_load", "true"); 
    

    手动指定动态链接库文件路径

    System.setProperty("jna.library.path",dllResourcePath);
    System.setProperty("jna.platform.library.path",dllResourcePath);
    

    4. 程序在运行一段时间后崩溃

    在JNA crash-protection 中,官方文档说明的崩溃的主要原因,( These are often caused by improper mappings or invalid arguments passed to the native library.) 未知的参数类型映射导致vm崩溃。在很大程度上使用 Pointer 来作为 Java 通用映射类型。而 JNA 默认程序保护Native.setProtected(true)使得 java 错误来代替程序崩溃,可以设置 Native.setProtected(false) 来 dump 出崩溃日志。

    问题可以反馈到 JNA Google Group : https://groups.google.com/forum/#!forum/jna-users

    6. 参考

    1. JNA Google Group : https://groups.google.com/forum/#!forum/jna-users

    2. JNA API Documentation: https://java-native-access.github.io/jna/4.2.1/overview-summary.html

    3. JNA VM Crashed Protection :http://java-native-access.github.io/jna/4.5.1/javadoc/overview-summary.html#crash-protection

  • 相关阅读:
    drone 学习五 集成gitlab 配置以及简单测试
    ambassador kubernetes native api gateway
    使用distillery 实现版本的动态升级&& 动态降级
    使用distillery 构建专业的 phoenix 项目软件包
    mix deps HEX_HTTP_CONCURRENCY=1 HEX_HTTP_TIMEOUT=120 timeout
    elixir jenkins 集成构建方式配置
    phoenix 使用activerecord模式框架ecto 访问数据库
    phoenxi elixir 框架几个方便的命令
    phoenix elixir 框架简单试用
    k8s helm 私服chartmuseum minio s3 存储配置
  • 原文地址:https://www.cnblogs.com/549294286/p/10835163.html
Copyright © 2020-2023  润新知