在Java中加载静态编译的库

时间:2016-10-03 23:45:30

标签: java c++ java-native-interface

我无法使用System.loadLibrary(“”)从Java加载静态编译的库,但我可以将其作为动态编译的库(当我以这种方式构建时)加载就好了。我正在使用JDK 8,我的理解是它可以通过System.loadLibrary(“”)加载静态库,如果你在* .cpp和* .h文件中提供JNI_OnLoad_L。

我的kdu_jni.h有:

extern "C"
JNIEXPORT jint JNICALL JNI_OnLoad_kdu_1jni(JavaVM *, void *);

我的kdu_jni.cpp有:

JNIEXPORT jint JNICALL JNI_OnLoad_kdu_1jni(JavaVM *vm, void *reserved)
{
  return JNI_VERSION_1_8;
}

当我尝试使用编译版本运行时,我的java.library.path目录中有libkdu_jni.a文件。当我尝试动态加载它时,它在同一目录中的libkdu_jni.so文件正常工作。当尝试使用静态文件(libkdu_jni.a)时,我得到:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no kdu_jni in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)

我在尝试加载.a文件之前取出了.so文件。

我不确定我做错了什么。我不认为它甚至看到libkdu_jni.a文件的JNI_OnLoad_kdu_1jni(),因为我在那里放了一个异常而且我没有看到被抛出。我在该名称上尝试了几次迭代:JNI_OnLoad_kdu_jni(),JNI_OnLoad_kdu_1jni(),JNI_OnLoad()等。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

  

我的理解是,如果你在* .cpp和* .h文件中提供JNI_OnLoad_L,它可以通过System.loadLibrary("")加载静态库。

您的理解不正确。您无法动态加载.a文件。它不能以任何形式或形式执行:

  • 基础设施参考文献尚未解决
  • 库外的引用也未解析:例如,解析到C库。

链接步骤是必不可少的,JVM并不适合您。您所阅读的内容适用于静态链接到JVM的库

答案 1 :(得分:0)

我建议您尝试使用JNI_OnLoad_kdu_jni作为函数名称。如果这不起作用,则可能无法使用包含下划线的库名称。

---原帖如下---

在Java 8之前,仅支持共享对象库。

这意味着要知道静态库是否为Java 8,必须在库中实现一个新函数。

JNI_OnLoad_libname must return a value of JNI_VERSION_1_8 or higher.

我猜测,因为你的代码是动态的,但不是静态的,也许这个函数不存在。下面的JEP 178部分让我相信这一点:

  

java.lang.System.loadLibrary和。的规范   java.lang.Runtime.loadLibrary方法将被修改为:

     

加载libname参数指定的本机库。 libname不得包含任何特定于平台的前缀,文件扩展名,   或路径。

     

如果名为libname的本机库与VM静态链接,则由JNI_OnLoad_libname函数导出   库被调用。有关详细信息,请参阅JNI规范。

     

否则,libname从系统库位置加载并映射到一个本机库映像   依赖于实现的方式。

Also the notes in the enhancement echo this sentiment

The source code for the loader is helpful

我在调试(gdb)下启动java并在Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib处放置一个断点。你是对的,没有很多很好的例子。