将静态库与JNI链接

时间:2014-06-30 15:11:33

标签: java java-native-interface static-libraries java-8 static-linking

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

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

3 个答案:

答案 0 :(得分:10)

Java SE 8规范已更改为支持静态链接,静态链接在JDK中实现。 System.loadLibrary的规范中简要提到了这一点。它引用的JNI规范的部分是herehere

静态方法签名和数据类型对于静态和动态链接的方法是相同的。您可能不得不破解JDK makefile以使其静态链接您的库。

一个重要的区别是静态库的初始化方式。通过调用JNI_OnLoad函数初始化动态库,并通过调用JNI_OnUnload取消初始化。每个动态库都可以拥有自己的这些函数版本。如果有多个静态链接库,显然它们都不能具有这些相同名称的函数。对于名为libname的静态库,加载/卸载功能为JNI_OnLoad_libnameJNI_OnUnload_libname

JNI_OnLoad_libname函数必须返回JNI_VERSION_1_8或更高的值。如果没有,JVM将忽略静态库。

基本上,如果您调用System.loadLibrary("foo"),系统会在正在运行的可执行映像中查找函数JNI_OnLoad_foo,如果找到它,则会假定该库是静态链接的,并且在运行图像中搜索其本机方法。如果找不到JNI_OnLoad_foo,则会进行动态库的常规搜索和加载,并且从找到的动态库链接本机方法。

答案 1 :(得分:3)

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

  

不需要更改现有Java代码,以便使用静态本机库而不是动态本机库。特别是System.loadLibrary(" foo")形式的方法调用应该能够加载" foo"库,无论该库是以静态还是动态形式提供的。

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

答案 2 :(得分:1)

Java 8增强https://openjdk.java.net/jeps/178用于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的。

参考: