加载静态编译的Java库

Load statically compiled library in Java

本文关键字:Java 编译 静态 加载      更新时间:2023-10-16

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

My kdu_jni.h has:

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

My kdu_jni.cpp has:

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

我有libkdu_jni。当我尝试使用编译后的版本运行时,我的java.library.path目录中的一个文件。它可以很好地与libkdu_jni一起工作。当我尝试动态加载时,在同一目录下。当尝试使用静态文件(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。一个文件的JNI_OnLoad_kdu_1jni()因为我在那里放了一个异常,我没有看到它被抛出。我已经尝试了几个迭代的名称:JNI_OnLoad_kdu_jni(), JNI_OnLoad_kdu_1jni(), JNI_OnLoad()等。

任何想法?

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

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

  • 库内引用未解析
  • 库外的引用也不解析:例如,到C库。

链接步骤是必要的,JVM不会为您完成它。您所阅读的内容适用于静态链接到JVM中的库

我建议您尝试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的本地库与虚拟机静态链接,则JNI_OnLoad_libname函数由库被调用。有关更多细节,请参阅JNI规范。

否则,libname从系统库位置加载,并映射到本地库映像具体实现相关的方式。

增强版中的注释也呼应了这一观点

加载器的源代码很有帮助

我会在调试(gdb)下启动java,并在Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib处设置断点。你说得对,好的例子并不多。