的System.loadLibrary不起作用。 UnsatisfiedLinkError为在链

2019-09-01 03:25发布

我有一个使用CPP共享库通过JNI libclient.so java程序Client.class。 为共享和使用CPP共享库libhttp.so libclient.so建成。

libclient.so和libhttp.so被放置在文件夹/home/client/lib64
Client.class被放置在/home/client/bin

客户端可以加载库

  1. System.load和环境变量LD_LIBRARY_PATH
  2. 的System.loadLibrary和-Djava.library.path

第一种方式工作正常。

export LD_LIBRARY_PATH = /home/client/lib64

java的-classpath ./bin客户端

该塞康方式失败。

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

当我把libhttp.so到/ usr / lib64的第二种方式工作正常。

为什么libclient.so正在寻找libhttp.so在/ usr / lib64下,如果我使用的System.loadLibrary? 我怎样才能解决这个问题,而不应对libhttp.so到/ usr / lib64下?

我的加载代码:

    //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;
          }
       }
    }

附加信息。

如果我有LDD测试libclient.so然后我看到:libhttp.so => not found如果我设置出口LD_LIBRARY_PATH = /家庭/客户/ lib64下,然后我看到:libhttp.so => /home/client/lib64/libhttp.so

Answer 1:

这样做的原因是,libclient.so是从你的JVM,这看起来加载java.library.path 。 然而,当libclient.so尝试加载libhttp.so,因此它不知道Java和只使用加载共享库的常规Linux方式(动态连接器ld.so ),它看起来在LD_LIBRARY_PATH和一些常用的目录,如/usr/lib64

我可能会使用去LD_LIBRARY_PATH从Java应用程序的启动脚本设置。 如果你不希望使用启动脚本,理论上你可以设置LD_LIBRARY_PATH从工艺本身。 然而,Java不允许这样做(只有System.getenv()而不是System.setenv()所以你需要编写是从Java调用,调用一个小的C库putenv()设置LD_LIBRARY_PATH

如果你建立libclient.so本身,你可以使用-rpath链接器标志来指定的动态链接程序应该寻找进一步需要的库文件的路径。 要小心,如果你指定一个相对路径,这将解释为相对于运行的应用程序的当前工作目录,而不是相对的位置libclient.so 。 要做到这一点,你需要使用$ORIGIN作为论据-rpath ,小心你的shell不展开此。

所以,如果你想拥有libclient.solibhttp.so在同一目录下,你需要使用

-rpath '$ORIGIN'

作为参数传递给连接建立时libclient.so 。 如果你不直接调用连接器而让你的编译器调用它,你需要以下内容添加到您的编译器的命令行:

-Wl,-rpath,'$ORIGIN'

关于这方面更多的信息可以在找到的手册页ld.so



Answer 2:

我对这个问题没有很好的答案。

但是,我发现了几个很好的方法。

  1. 放libhttp.so成库共享位置,例如在/ usr / lib64下。
  2. 把路径libhttp.so到LD_LIBRARY_PATH。
  3. 构建libclient.so与libhttp.so内。
  4. libclient.so的建设过程中使用-rpath。


Answer 3:

对于库(来自的java.library.path)针对不同操作系统的正确查找的必须有不同的名称:

  • Linux操作系统:libhttp.so
  • Windows系统:http.dll

比你可以从Java调用:

System.loadLibrary( "http" );


文章来源: System.loadLibrary does not work. UnsatisfiedLinkError for the second lib in chain