【发布时间】:2011-08-15 20:04:37
【问题描述】:
我想在我的 java 应用程序中加载我自己的本地库。这些本机库依赖于第三方库(当我的应用程序安装在客户端计算机上时,这些库可能存在也可能不存在)。
在我的 java 应用程序中,我要求用户指定依赖库的位置。获得此信息后,我将使用它来使用 JNI 代码更新“LD_LIBRARY_PATH”环境变量。以下是我用来更改“LD_LIBRARY_PATH”环境变量的代码sn-p。
Java 代码
public static final int setEnv(String key, String value) { 如果(键==空){ throw new NullPointerException("key 不能为 null"); } 如果(值 == 空){ throw new NullPointerException("值不能为空"); } 返回nativeSetEnv(键,值); } public static final native int nativeSetEnv(String key, String value);Jni 代码 (C)
JNIEXPORT jint JNICALL Java_Test_nativeSetEnv(JNIEnv *env, jclass cls, jstring key, jstring value) { const char *nativeKey = NULL; 常量字符 *nativeValue = NULL; nativeKey = (*env)->GetStringUTFChars(env, key, NULL); nativeValue = (*env)->GetStringUTFChars(env, value, NULL); int result = setenv(nativeKey, nativeValue, 1); 返回(jint)结果; }我也有相应的本地方法来获取环境变量。
我可以成功更新 LD_LIBRARY_PATH(此断言基于 C 例程 getenv() 的输出。
我仍然无法加载我的原生库。仍然没有检测到依赖的第三方库。
感谢任何帮助/指针。我使用的是 64 位 Linux。
编辑:
我写了一个 SSCE(用 C 语言)来测试动态加载器是否工作。这是SSCE
#包括 #包括 #包括 #包括 int main(int argc, const char* const argv[]) { const char* constdependentLibPath = "...:"; const char* const sharedLibrary = "..."; 字符 *newLibPath = NULL; 字符 *originalLibPath = NULL; int l1,l2,结果; 无效*句柄 = NULL; originalLibPath = getenv("LD_LIBRARY_PATH"); fprintf(stdout,"\n原始库路径 =%s\n",originalLibPath); l1 = strlen(originalLibPath); l2 = strlen(dependentLibPath); newLibPath = (char *)malloc((l1+l2)*sizeof(char)); strcpy(newLibPath,dependentLibPath); strcat(newLibPath,originalLibPath); fprintf(stdout,"\n新库路径 =%s\n",newLibPath); 结果 = setenv("LD_LIBRARY_PATH", newLibPath, 1); 如果(结果!= 0){ fprintf(stderr,"\n环境无法更新\n"); 退出(1); } newLibPath = getenv("LD_LIBRARY_PATH"); fprintf(stdout,"\n来自 env 的新库路径 =%s\n",newLibPath); 句柄 = dlopen(sharedLibrary, RTLD_NOW); 如果(句柄==NULL){ fprintf(stderr,"\n无法加载共享库:%s\n",dlerror()); 退出(1); } fprintf(stdout,"\n 共享库加载成功。\n"); 结果 = dlclose(句柄); 如果(结果!= 0){ fprintf(stderr,"\n无法卸载共享库:%s\n",dlerror()); 退出(1); } 返回0; }C 代码也不起作用。显然,动态加载程序没有重新读取 LD_LIBRARY_PATH 环境变量。我需要弄清楚如何强制动态加载器重新读取 LD_LIBRARY_PATH 环境变量。
【问题讨论】:
-
我真的不明白为什么它不起作用,因为我做了一些非常相似的事情(在 Windows 下),它就像一个魅力。顺便说一句,您是否尝试过(仅出于调试目的)使用 System.load(...) 将库加载到“默认”库目录中,以查看库是否已损坏(而不是您的 nativeSetEnv 代码) .但是,好问题 (+1)
-
..这是题外话,但我认为你应该释放由 GetStringUTFChars 分配的内存
-
@Giacomo:如果我在启动我的应用程序时设置了 LD_LIBRARY_PATH,它就可以工作。我将释放分配的内存。感谢您指出。 :)
-
我讨厌这样告诉你,但是有一个激进的“解决方案”可以帮助你克服这个问题。删除 JNI,创建一个在 Java 应用程序和该库之间进行调解的本机可执行文件。我记得在与这些杂乱无章的 JNI 事情(比如动态加载依赖库)进行了很多斗争之后,我在 Java 和动态库之间创建了一个 trait-union,其中包含一个使用 stdin 和 stdout 与 Java 通信的本机可执行文件,并且在极少数情况下使用文件系统(临时文件)。讨厌但很容易实现。
-
所以我原来的评论是错误的。那是很久以前。在与 JNI 进行了很多斗争之后,我已经按照我在上一篇中所说的那样做了。评论。这可能更难或更容易,具体取决于 Java 和本机共享的数据量。如果您有兴趣,请参阅 ProcessBuilder 类。
标签: java loadlibrary setenv