System.loadLibrary does not work. UnsatisfiedLinkError for the second lib in chain

流过昼夜 提交于 2019-12-30 02:27:25

问题


I have java program Client.class that uses cpp shared library libclient.so via JNI. libclient.so is built as shared and uses cpp shared library libhttp.so.

libclient.so and libhttp.so are placed in folder /home/client/lib64
Client.class is placed in /home/client/bin

Client can load library with

  1. System.load and environment variable LD_LIBRARY_PATH
  2. System.loadLibrary and -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 I put libhttp.so into /usr/lib64 the second way works fine.

Why libclient.so is looking for libhttp.so in /usr/lib64 if I use System.loadLibrary? How can I fix it without coping libhttp.so into /usr/lib64?

My loading code:

    //Try load from -Djava.library.path        
    boolean found = false;
    String lib = "client";
    try {
       System.loadLibrary(lib);
       found = true;
    } catch (UnsatisfiedLinkError e) {
       e.printStackTrace();
    }
    //Try load from 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 I test libclient.so with ldd then I see: libhttp.so => not found If I set export LD_LIBRARY_PATH = /home/client/lib64 then I see: libhttp.so => /home/client/lib64/libhttp.so


回答1:


The reason for this is that libclient.so is loaded from your JVM, which looks in java.library.path. However, when libclient.so tries to load libhttp.so, it knows nothing about Java and just uses the regular Linux way of loading shared libraries (the dynamic linker ld.so), which looks in LD_LIBRARY_PATH and some common directories like /usr/lib64.

I would probably go with using LD_LIBRARY_PATH set from a start script of your Java application. If you don't want to use a start script, you could in theory set LD_LIBRARY_PATH from within the process itself. However, Java does not allow to do this (there is only System.getenv(), not System.setenv()), so you would need to write a small C library that is called from Java and calls putenv() setting LD_LIBRARY_PATH.

If you build libclient.so itself, you can use the -rpath linker flag to specify a path where the dynamic linker should look for further required libraries. Be careful if you specify a relative path here, it will interpreted as relative to the current working directory of the running application, not relative to the location of libclient.so. To achieve this, you need to use $ORIGIN as argument for -rpath and be careful that your shell does not expand this.

So, if you want to have libclient.so and libhttp.so in the same directory, you need to use

-rpath '$ORIGIN'

as argument to the linker when building libclient.so. If you do not call the linker directly but let your compiler call it, you need to add the following to your compiler's command line:

-Wl,-rpath,'$ORIGIN'

More information about this can be found in the man page for ld.so.




回答2:


I have no good answer for this question.

But I found several good ways.

  1. Put libhttp.so into shared location for libraries, for example /usr/lib64.
  2. Put path to libhttp.so into LD_LIBRARY_PATH.
  3. Build libclient.so with libhttp.so inside.
  4. Use -rpath during building of libclient.so.



回答3:


For correct lookup of library (from java.library.path) for different OS's must have different names:

  • Linux: libhttp.so
  • Windows: http.dll

Than you can call from Java:

System.loadLibrary( "http" );


来源:https://stackoverflow.com/questions/16215197/system-loadlibrary-does-not-work-unsatisfiedlinkerror-for-the-second-lib-in-cha

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!