Java 将静态库与JNI链接

Java 将静态库与JNI链接,java,java-native-interface,static-libraries,java-8,static-linking,Java,Java Native Interface,Static Libraries,Java 8,Static Linking,Java 8之前的Java版本要求本机代码位于共享库中,但我已经了解到,使用Java 8可以将静态链接库与JNI结合使用。我已经搜索了一些例子,但没有找到 如何将JNI库静态链接到java应用程序中?根据您在评论中链接到的JEP178,您不必做任何不同的事情System.loadLibrary现在将同时加载动态库和静态库 为了使用静态本机库而不是动态本机库,不需要更改现有Java代码。尤其是表单System.loadLibrary(“foo”)的方法调用应该能够加载“foo”库,而不管该库是以静

Java 8之前的Java版本要求本机代码位于共享库中,但我已经了解到,使用Java 8可以将静态链接库与JNI结合使用。我已经搜索了一些例子,但没有找到


如何将JNI库静态链接到java应用程序中?

根据您在评论中链接到的JEP178,您不必做任何不同的事情
System.loadLibrary
现在将同时加载动态库和静态库

为了使用静态本机库而不是动态本机库,不需要更改现有Java代码。尤其是表单System.loadLibrary(“foo”)的方法调用应该能够加载“foo”库,而不管该库是以静态形式还是动态形式提供的


您可能只需要确保java.library.path设置正确。

java SE 8规范已更改为支持静态链接,并且静态链接在JDK中实现。在的规范中简要提到了这一点。它所引用的JNI规范的部分是和

静态链接方法和动态链接方法的本机方法签名和数据类型相同。不过,您可能必须破解JDK makefiles,使其静态链接库

一个显著的区别是静态库的初始化方式。动态库通过调用
JNI\u OnLoad
函数初始化,并通过调用
JNI\u OnLoad
反初始化。每个动态库都可以有自己版本的这些函数。如果有多个静态链接库,显然它们不可能都有同名函数。对于名为
libname
的静态库,加载/卸载函数是
JNI_OnLoad_libname
JNI_OnUnload_libname

JNI\u OnLoad\u libname
函数必须返回
JNI\u VERSION\u 1\u 8
或更高的值。如果没有,JVM将忽略静态库

基本上,如果调用
System.loadLibrary(“foo”)
,系统会在正在运行的可执行映像中查找函数
JNI\u OnLoad\u foo
,如果找到该函数,它会假定该库是静态链接的,并在运行映像中搜索其本机方法。如果未找到
JNI\u OnLoad\u foo
,则会进行通常的动态库搜索和加载,并从找到的动态库链接本机方法。

Java 8增强功能是针对JVM的

给定两个文件:

  • Main.java
  • Main.c
创建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
创建libnative.a:

ar -cvq libnative.a Main.o
对于每个libnative.a、libnative.so,通过以下方式运行测试:

java -Djava.library.path=.  Main
结果:

  • libnative.so
  • libnative.a
这证明178是用于JVM的

参考资料:


你在哪里读到的?请提供一些证据:-)在Wikipedia的Java版本历史页面上看到了,他们的来源:因此,与共享库相比,我需要做的唯一不同的事情就是编译它不同?C/C++代码没有更改?@user3525110 Java或C代码都没有更改。只要使用您通常使用的任何编译器选项,从C编译的对象文件创建一个共享或静态库。这真的有效吗?我得到了一个静态库(.a文件),但即使我正确设置了java.library.path,也找不到该库:“线程中的异常”main“java.lang.unsatifiedlinkerror:no in java.library.path”。我使用的是Java8和Debian。@little_planet:不,您不能简单地将静态库复制到路径中。新方法只适用于那些将JVM嵌入到可执行文件中的人。谢谢你的回答。但现在我有点不确定。我仍然可以使用
javah
为源代码创建头文件,还是需要自己命名方法等?@chmod编写本机方法本身的机制应该与动态本机方法相同。与静态的区别在于,您必须编译并链接本机代码以生成静态库,然后执行第二步将该静态库链接到JVM本身。好的,您知道如何修改我的JDK以使其与库一起工作吗?@chmod我认为您不能修改预建的JDK,因为(我相信)不能将其他静态库链接到可执行文件中。如果您是从源代码构建的,则可能需要使用其他参数或变量设置来破解makefile,以便为linker命令提供静态库。例如,请参阅OpenJDK中第320行附近的内容,不要忘记让
JNI_OnLoad_X
函数至少返回
JNI_VERSION_1_8
,否则库将被静默忽略。