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\n");
        for (int i=0;i < args.length;i++) {
            CLibrary.INSTANCE.printf("Argument %d: %s\n", 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM