Java 使用 JNI 链接静态库
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24493337/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Linking static library with JNI
提问by chmod
Java versions prior Java 8 requires native code to be in a shared library, but I've read that with Java 8 it's possible to use static linked libraries with JNI. I have searched for examples but couldn't find any.
Java 8 之前的 Java 版本要求本机代码位于共享库中,但我读过使用 Java 8 可以将静态链接库与 JNI 一起使用。我已经搜索了示例,但找不到任何示例。
How can I statically link a JNI library into my java application?
如何将 JNI 库静态链接到我的 Java 应用程序?
采纳答案by Stuart Marks
The Java SE 8 specification has been changed to support static linking, and static linking is implemented in the JDK. This is mentioned briefly in the spec for System.loadLibrary. The sections of the JNI Specification to which it refers are hereand here.
Java SE 8 规范已更改为支持静态链接,并且在 JDK 中实现了静态链接。System.loadLibrary的规范中简要提到了这一点。它所引用的 JNI 规范部分在此处和此处。
Native method signatures and data types are the same for statically and dynamically linked methods. You might have to hack on the JDK makefiles to get it to link your library statically, though.
本机方法签名和数据类型对于静态和动态链接的方法是相同的。不过,您可能必须破解 JDK 生成文件才能使其静态链接您的库。
One significant difference is the way static libraries are initialized. Dynamic libraries are initialized by calling the JNI_OnLoad
function and are deinitialized by calling JNI_OnUnload
. Each dynamic library can have its own version of these functions. If there are multiple statically linked libraries, clearly they can't all have functions with these same names. For a static library named libname
the load/unload functions are JNI_OnLoad_libname
and JNI_OnUnload_libname
.
一个显着的区别是静态库的初始化方式。动态库通过调用JNI_OnLoad
函数初始化,通过调用取消初始化JNI_OnUnload
。每个动态库都可以有自己的这些函数版本。如果有多个静态链接的库,显然它们不能都具有相同名称的函数。对于名为libname
加载/卸载函数的静态库是JNI_OnLoad_libname
和JNI_OnUnload_libname
。
The JNI_OnLoad_libname
function must return a value of JNI_VERSION_1_8
or higher. If it doesn't, the JVM will ignore the static library.
该JNI_OnLoad_libname
函数必须返回JNI_VERSION_1_8
或更高的值。如果没有,JVM 将忽略静态库。
Basically, if you call System.loadLibrary("foo")
, the system looks for the function JNI_OnLoad_foo
in the running executable image, and if it's found, it assumes that the library is statically linked, and its native methods are searched for within the running image. If JNI_OnLoad_foo
is not found, then the usual searching and loading of dynamic libraries takes place, and native methods are linked from the dynamic library so found.
基本上,如果您调用System.loadLibrary("foo")
,系统会JNI_OnLoad_foo
在正在运行的可执行映像中查找该函数,如果找到,则假定该库是静态链接的,并在运行映像中搜索其本机方法。如果JNI_OnLoad_foo
未找到,则进行通常的动态库搜索和加载,并且从如此找到的动态库链接本机方法。
回答by dkatzel
Accoding to the JEP 178 you linked to in your comment, you don't have to do anything differently. System.loadLibrary
will now load both dynamic and static libraries.
根据您在评论中链接的 JEP 178,您不必做任何不同的事情。System.loadLibrary
现在将加载动态和静态库。
Require no changes to existing Java code in order to use a static native library as opposed to a dynamic native library. A method invocation of the form System.loadLibrary("foo"), in particular, should be able to load the "foo" library regardless of whether that library is provided in static or dynamic form.
无需更改现有 Java 代码即可使用静态本机库而不是动态本机库。尤其是 System.loadLibrary("foo") 形式的方法调用应该能够加载“foo”库,无论该库是以静态形式还是动态形式提供。
You probably just need to make sure your java.library.path is set correctly.
您可能只需要确保您的 java.library.path 设置正确。
回答by typelogic
The Java 8 enhancement https://openjdk.java.net/jeps/178is meant for the JVM.
Java 8 增强https://openjdk.java.net/jeps/178适用于 JVM。
Given two files:
给定两个文件:
- Main.java
- Main.c
- 主程序
- 主文件
Create libnative.so:
创建 libnative.so:
javac Main.java
javah Main
gcc -c Main.c
gcc -c Main.c -I /home/dx/.sdkman/candidates/java/current/include/linux -I /home/dx/.sdkman/candidates/java/current/include
gcc -shared -o libnative.so Main.o
Create libnative.a:
创建 libnative.a:
ar -cvq libnative.a Main.o
For each libnative.a, libnative.so test run via:
对于每个 libnative.a,通过以下方式运行 libnative.so 测试:
java -Djava.library.path=. Main
Result:
结果:
- Success execution when
libnative.so
- Fail execution when
libnative.a
- 成功执行时
libnative.so
- 执行失败时
libnative.a
This proves that 178is for the JVM.
这证明178是针对JVM的。
References:
参考: