linux系統調用syscall 表:https://filippo.io/linux-syscall-table/html
原文:https://iliangqunru.bitcron.com/post/2018/jna-shi-ji-kai-fa-zhong-ruo-gan-wen-ti-jie-jue-fang-falinux
其餘:git
JNI的替代者—使用JNA訪問Java外部功能接口github
java發起系統調用,本質仍是用了JNA,調用OS提供的syacall函數:oracle
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 有了入坑體驗,對實際工做中遇到的問題作出總結。app
<dependency>
<groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>latest</version> </dependency>
接口生成dom
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");
直接映射ide
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]); } } }
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".
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) | Buffer |
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 |
儘管 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位 |
存在多個動態連接庫之間調用狀況,可能缺乏其中某一個動態連接庫文件。
較大狀況下存在參數類型映射錯誤,參考 JNA 類型映射。
沒法加載到動態連接庫文件路徑,須要將動態連接庫放到項目根目錄下,推薦開啓 JNA 驅動加載 debug 模式,
System.setProperty("jna.debug_load", "true");
手動指定動態連接庫文件路徑
System.setProperty("jna.library.path",dllResourcePath); System.setProperty("jna.platform.library.path",dllResourcePath);
在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
JNA Google Group : https://groups.google.com/forum/#!forum/jna-users
JNA API Documentation: https://java-native-access.github.io/jna/4.2.1/overview-summary.html
JNA VM Crashed Protection :http://java-native-access.github.io/jna/4.5.1/javadoc/overview-summary.html#crash-protection