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