0
votes

On Ubuntu 16.04, I'm building a JNI library against another shared library. The dependency is OpenCv, version 3.4.0, built locally and not installed in a standard library path.

I'm using cmake from maven to build the my JNI library. The output of the compile and link lines are as follows:

[ 66%] Building CXX object CMakeFiles/lib-image-native.jiminger.com.dir/sources/CvRasterNative.cpp.o /usr/bin/c++ -DUNIX -Dlib_image_native_jiminger_com_EXPORTS -I/usr/lib/jvm/java-8-openjdk-amd64/include -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux -I/home/jim/src/opencv-packaging/package-native/target/cmake -I/home/jim/utils/opencv-3.4.0/installed/include -fPIC -std=gnu++11 -o CMakeFiles/lib-image-native.jiminger.com.dir/sources/CvRasterNative.cpp.o -c /home/jim/src/opencv-packaging/package-native/target/sources/sources/CvRasterNative.cpp [100%] Linking CXX shared module liblib-image-native.jiminger.com.so /home/jim/src/opencv-packaging/package-native/target/dependency/cmake/bin/cmake -E cmake_link_script CMakeFiles/lib-image-native.jiminger.com.dir/link.txt --verbose=1 /usr/bin/c++ -fPIC -shared -o liblib-image-native.jiminger.com.so CMakeFiles/lib-image-native.jiminger.com.dir/sources/CvRasterNative.cpp.o -Wl,-rpath,/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/libjawt.so /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server/libjvm.so

When I run a test that calls my native function I get:

.../java: symbol lookup error: [path to my library].so: undefined symbol: _ZN2cv6String8allocateEm

Inside my java code I'm explicitly loading this library (using System.load) as well as the dependent OpenCv library. That symbol is in the OpenCv library that I'm explicitly System.load'ing.

nm [path to opencv shared library].so | grep _ZN2cv6String8allocateEm

gives

0000000000442990 t _ZN2cv6String8allocateEm

When I call into my library I get that error. It says the symbol is undefined. But it's definition is in the other library (notice, it's in the 'text' segment) which I'm explicitly loading.

Can someone please tell me what I'm missing?

Thanks

EDIT: If it makes a difference, when I ldd my shared library I get

linux-vdso.so.1 =>  (0x00007ffe6e58f000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f7d279dc000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f7d277c5000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7d273fb000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7d270f2000)
/lib64/ld-linux-x86-64.so.2 (0x00005574eb402000)
1
Have you updated LD_LIBRARY_PATH to include the directories of the .so files and/or have you run Java with the -Djava.libary.path argument?stdunbar
I eventually tried that but I didn't expect it to work. I'm System.load'ing the files with the full path. I'm not using System.loadLibrary. I'm calling System.load("full path to .so file"); for each library.Jim

1 Answers

0
votes

I figured out what the problem was. I didn't realize the output of the nm command shows local (vs externally visible) symbols. From the man page for nm:

The symbol type. At least the following types are used; others are, as well, depending on the object file format. If lowercase, the symbol is usually local; if uppercase, the symbol is global (external).

The symbol in the dependent library is local indicated by the lower case 't'.