java - System.loadLibrary does not work. UnsatisfiedLinkError for the second lib in chain -
i have java program client.class uses cpp shared library libclient.so via jni. libclient.so built shared , uses cpp shared library libhttp.so.
libclient.so , libhttp.so placed in folder /home/client/lib64
client.class placed in /home/client/bin
client can load library with
- system.load , environment variable ld_library_path
- system.loadlibrary , -djava.library.path
the first way works fine.
export ld_library_path = /home/client/lib64
java -classpath ./bin client
the secon way fails.
java -classpath ./bin -djava.library.path=./../lib64 client
java.lang.unsatisfiedlinkerror: /home/client/lib64/libclient.so: libhttp.so: cannot open shared object file: no such file or directory
when put libhttp.so /usr/lib64 second way works fine.
why libclient.so looking libhttp.so in /usr/lib64 if use system.loadlibrary? how can fix without coping libhttp.so /usr/lib64?
my loading code:
//try load -djava.library.path boolean found = false; string lib = "client"; try { system.loadlibrary(lib); found = true; } catch (unsatisfiedlinkerror e) { e.printstacktrace(); } //try load ld_library_path if (!found) { lib = "libclient.so"; string ld_lib_path = system.getenv("ld_library_path"); string[] paths = ld_lib_path.split(":"); for(int i=0; i<paths.length; i++) { string p = paths[i]; file x = new file(p, lib); if (x.exists()) { system.load(x.getabsolutepath()); found = true; break; } } }
additional information.
if test libclient.so ldd see: libhttp.so => not found if set export ld_library_path = /home/client/lib64 see: libhttp.so => /home/client/lib64/libhttp.so
the reason libclient.so loaded jvm, looks in java.library.path
. however, when libclient.so tries load libhttp.so, knows nothing java , uses regular linux way of loading shared libraries (the dynamic linker ld.so
), looks in ld_library_path
, common directories /usr/lib64
.
i go using ld_library_path
set start script of java application. if don't want use start script, in theory set ld_library_path
within process itself. however, java not allow (there system.getenv()
, not system.setenv()
), need write small c library called java , calls putenv()
setting ld_library_path
.
if build libclient.so
itself, can use -rpath
linker flag specify path dynamic linker should further required libraries. careful if specify relative path here, interpreted relative current working directory of running application, not relative location of libclient.so
. achieve this, need use $origin
argument -rpath
, careful shell not expand this.
so, if want have libclient.so
, libhttp.so
in same directory, need use
-rpath '$origin'
as argument linker when building libclient.so
. if not call linker directly let compiler call it, need add following compiler's command line:
-wl,-rpath,'$origin'
more information can found in man page ld.so
.