我无法使用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()等。
有什么想法吗?
答案 0 :(得分:2)
我的理解是,如果你在* .cpp和* .h文件中提供JNI_OnLoad_L,它可以通过System.loadLibrary("")加载静态库。
您的理解不正确。您无法动态加载.a
文件。它不能以任何形式或形式执行:
链接步骤是必不可少的,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
处放置一个断点。你是对的,没有很多很好的例子。