在Java eclipse(Linux)上使用JNI,我正在加载名为 first.so 的动态共享库。 到目前为止一切顺利。 问题是, first.so 还会加载名为 second.so 的动态库。
运行程序时,我收到很多关于位于 second.so 中的符号的“未定义符号”错误。
使用JNI加载的库似乎无法在运行时加载其他C库,因为我们在Java环境中。我的假设是否正确? 我是否需要特殊的编译标志来编译 first.so 库,或者是告诉eclipse它将在运行时尝试加载.so的特殊参数吗?
提前致谢!
答案 0 :(得分:2)
使用JNI加载的库似乎无法在运行时加载其他C库,因为我们在Java环境中。我的假设是否正确?
没有
libsecond.so
如何使用libfirst.so
?它是链接依赖项,还是由dlopen
加载?
我发现了类似的东西:
static {
System.loadLibrary("second");
System.loadLibrary("first");
}
在使用JNI的类中通常有效。
编辑:现在我知道你如何加载libsecond.so
这对我有用了:
<强> Test.java 强>
public class Test {
public static void main (String args[]) {
test();
}
private native static void test();
static {
System.loadLibrary("first");
}
}
first.c - libfirst.so
#include <jni.h>
#include "Test.h"
#include <dlfcn.h>
#define LIBNAME "libsecond.so"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Test
* Method: test
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_Test_test(JNIEnv *env , jclass cls)
{
void* h;
void (*sym)(void);
h = dlopen(LIBNAME, RTLD_LAZY|RTLD_GLOBAL);
if (h) {
printf("dlopen " LIBNAME " worked\n");
sym = (void (*)(void))dlsym(h,"second");
sym();
} else {
printf("dlopen " LIBNAME " failed\n");
}
}
#ifdef __cplusplus
}
#endif
second.c - libsecond.so
#include <stdio.h>
void
second(void)
{
printf("hello from second\n");
}
<强>生成文件强>
CFLAGS=-fPIC
all : libfirst.so libsecond.so
libsecond.so : second.o
$(CC) -shared -Wl,-soname,libsecond.so.0 -o $@ $^ -lc
libfirst.so : first.o
$(CC) -shared -Wl,-soname,libfirst.so.0 -o $@ $^ -ldl -lc
clean:
rm -f *.o *.so
Test.h
可由javah Test
制作。请注意,libfirst.so
和libsecond.so
未链接在一起。
答案 1 :(得分:0)
所有常用规则适用于从Java加载的库中的dopen()
。特别是,您需要检查LD_LIBRARY_PATH,rpath, runpath等。另请参阅dlopen failed:cannot open shared object file: No such file or directory