System.loadLibrary不起作用。链中的第二个lib的UnsatisfiedLinkError [英] System.loadLibrary does not work. UnsatisfiedLinkError for the second lib in chain

查看:166
本文介绍了System.loadLibrary不起作用。链中的第二个lib的UnsatisfiedLinkError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有java程序Client.class,它通过JNI使用cpp共享库libclient.so。
libclient.so构建为共享并使用cpp共享库libhttp.so。

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和libhttp.so放在文件夹<$ c $中c> / home / client / lib64

Client.class位于 / home / client / bin

libclient.so and libhttp.so are placed in folder /home/client/lib64
Client.class is placed in /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 Client

java -classpath ./bin Client

secon方式失败。

The secon way fails.

java -classpath ./bin -Djava.library.path =。/ .. / lib64客户端

java.lang.UnsatisfiedLinkError: /home/client/lib64/libclient.so: libhttp.so: cannot open shared object file: No such file or directory

当我将libhttp.so放入/ usr / lib64时,第二种方式有效很好。

When I put libhttp.so into /usr/lib64 the second way works fine.

如果我使用System.loadLibrary,为什么libclient.so在/ usr / lib64中寻找libhttp.so?
如何在不将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 =>找不到
如果我设置export LD_LIBRARY_PATH = / home / client / lib64然后我看到:libhttp.so => /home/client/lib64/libhttp.so

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

推荐答案

原因是libclient.so从JVM加载,它在 java.library.path 中查找。但是,当libclient.so尝试加载libhttp.so时,它对Java一无所知,只使用常规Linux方式加载共享库(动态链接器 ld.so ) ,查看 LD_LIBRARY_PATH 和一些常见目录,如 / usr / lib64

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.

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

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.

如果您自己构建 libclient.so ,则可以使用 -rpath 链接器标志来指定路径其中动态链接器应查找其他所需的库。如果在此处指定相对路径,请小心,它将被解释为相对于正在运行的应用程序的当前工作目录,而不是相对于 libclient.so 的位置。要实现这一点,您需要使用 $ ORIGIN 作为 -rpath 的参数,并注意您的shell不会扩展这个。

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.

所以,如果你想要 libclient.so libhttp.so 在同一目录中,您需要使用

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

-rpath '$ORIGIN'

作为构建 libclient.so 时链接器的参数。如果不直接调用链接器但让编译器调用它,则需要将以下内容添加到编译器的命令行中:

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'

有关此内容的更多信息,请参阅<一个 ld.so 手册页>。

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

这篇关于System.loadLibrary不起作用。链中的第二个lib的UnsatisfiedLinkError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆