jni需要加载库,并且该库是基于某个静态库的。但是在执行jni时,我得到了静态库中定义的und符号。
我使用静态库来构建动态库,并在java程序中加载动态库。
Makefile:
sudo cp /home/daniel/projects/leveldb/libleveldb.a libleveldb.a
g++ -shared -o libTest.so -fPIC -I/usr/lib/jvm/java-8-oracle/include/ -I/usr/lib/jvm/java-8-oracle/include/linux/ -L. -L/usr/lib/vmware-ovftool/lib/ libleveldb.a -lpthread Test.cpp
Test.cpp:
#include "Test.h"
#include <leveldb/db.h>
#include <iostream>
#include <cstdlib>
using namespace std;
JNIEXPORT void JNICALL Java_Test_getStringFromC(JNIEnv *, jobject)
{
printf("worldn");
cout<<"hahahan";
leveldb::DB *db = nullptr;
leveldb::Options options;
options.create_if_missing = true;
leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb",&db);
...
cmd:java测试结果:
java: symbol lookup error: /usr/lib/libTest.so: undefined symbol: _ZN7leveldb7OptionsC1Ev
cmd:readelf-s libleveldb.a|grep leveldb7选项结果:
169: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _ZN7leveldb7OptionsC1Ev
109: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _ZN7leveldb7OptionsC1Ev
48: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _ZN7leveldb7OptionsC1Ev
8: 0000000000000000 108 FUNC GLOBAL DEFAULT 1 _ZN7leveldb7OptionsC2Ev
12: 0000000000000000 108 FUNC GLOBAL DEFAULT 1 _ZN7leveldb7OptionsC1Ev
这意味着,我可以在静态库中找到符号,但在基于libleveldb.a的动态库中,jni程序找不到相同的符号。我想知道原因和正确的方式来完成它。
要使用静态库,需要将其与可执行文件静态链接。
在Java的情况下,这意味着您需要将其与java
可执行文件链接。这意味着每次运行Java应用程序时都需要重新组装它,但这将非常不方便。