【问题标题】:How to debug a java system.loadlibrary error in linux?如何在 linux 中调试 java system.loadlibrary 错误?
【发布时间】:2012-11-20 14:59:18
【问题描述】:

我有一个通过 JNI 调用 C 代码的 Java 程序,我试图在 Linux 上运行该程序。外部代码由两个 .so 文件组成:一个用于 JNI 绑定(使用 swig 构建),另一个用于实际功能。我在同一个目录中有两个库,并且 LD_LIBRARY_PATH 设置正确。 ldd 从命令行运行时没有报告任何问题,但是当我在 Eclipse 编辑器的“运行配置”对话框中将 LD_LIBRARY_PATH 设置为相同的值并尝试执行程序时,会出现以下错误:

java.lang.UnsatisfiedLinkError: [path to libraries]/[JNI binding library].so: [actual code library].so: cannot open shared object file: No such file or directory

这让我相信 JNI 包装器库已成功加载,但是当该库尝试加载包含实际代码的库时会失败。有什么办法可以进一步调试吗?

我会进一步指出,这个问题发生在 eclipse 编辑器本身中,我没有尝试将代码打包到 jar 中并在独立的 jvm 实例中运行。

【问题讨论】:

    标签: java eclipse java-native-interface


    【解决方案1】:

    我认为问题在于对 System.loadLibrary(String) 的调用和使用 LD_LIBRARY_PATH。使用 loadLibrary("foo") 将在您的 java.library.path 中查找名为 libfoo.so 的内容。如果找不到任何名为 libfoo.so 的文件,您将收到此错误。

    现在,如果您只是设置了 LD_LIBRARY_PATH,链接器会自动获取您想要的本地符号,因此您无需设置 -Djava.library.path。

    根据我在 gdal 项目中 swig 的经验,这个错误实际上是无害的,并且由于设置了 LD_LIBRARY_PATH,这将正常工作。

    我建议使用 -Djava.library.path 并显式调用 loadLibrary,原因是如果您决定使用 webstart 部署应用程序,您将明确需要调用 loadLibrary 来获取您的本机库。

    当我使用 Eclipse 时,我按照 Daff 提供的说明在构建路径的库选项卡中的 jar 下编辑本机库。再说一遍,这只是将 java.library.path 隐藏起来。

    【讨论】:

      【解决方案2】:

      您可能只需要在运行配置对话框中找到正确的位置来放置 -Djava.library.path=... 选项。我认为你想 -D 在参数选项卡上的“vm参数”中定义,而如果你想定义环境选项卡上的 LD_LIBRARY_PATH 。 Eclipse 会很高兴地让你把东西放在它们不代表你认为它们的意思的地方。无论如何,我以前以这种方式使用过库,如果有机会,我会查找我所做的并在此处编辑我的答案。

      要尝试的另一件事是使用 LD_DEBUG。您可以将环境变量 LD_DEBUG 设置为各种事物(尝试 ALL),然后 linux 加载器将泄露有关应用程序尝试加载的内容、哪里它正在寻找事物等的各种有用信息. 当然,这假设您从命令行启动 eclipse,因此您既可以设置环境变量,也可以查看加载程序诊断;但就系统而言,当您从 eclipse 内部运行您的应用程序时,您的应用程序只是 eclipse 正在做的事情,因此任何库加载行为都可以通过这种方式看到。

      【讨论】:

        【解决方案3】:

        也许你可以在命令行参数中尝试-Djava.library.path=actual.so

        在 Windows 上,我在使用 JNI 包装 DLL 作为其 DLL 的 3rd 方库时遇到了类似的问题。我的项目在 lib 目录中有 DLL,所以我将 lib 添加到 PATH(例如 PATH=%PATH%;./lib 环境变量,一切都开始工作了。

        【讨论】:

          【解决方案4】:

          据我所知,Eclipse 不使用 LD_LIBRARY_PATH。 设置正确的本机库路径的最简单方法是转到 项目属性 -> Java 构建路径 -> 库 然后展开 JRE 系统库条目或(如果可用) 使用本机库的 Jar 文件, 选择“Native Library Location”,然后单击“Edit...”并选择您的库所在的文件夹。实际上它确实设置了 -Djava.library.path 变量,因此如果您启动程序,您必须将其包含在命令行中来自日食之外。

          【讨论】:

            【解决方案5】:

            您的两个库还依赖于其他库吗?如果是这样,您需要确保 JVM 也可以访问它们。

            请注意,手动设置“-Djava.library.path”似乎会删除默认库路径。

            所以用下面的代码:

            public class LibTest {
                public static void main(String[] args) {
                    String property = System.getProperty("java.library.path");
                    StringTokenizer parser = new StringTokenizer(property, ":");
                    while (parser.hasMoreTokens()) {
                        System.err.println(parser.nextToken());
                    }
                }
            }
            

            使用 Java 1.6.0_14 输出从 eclipse 启动:

            /opt/java/jre/lib/i386/client
            /opt/java/jre/lib/i386
            /opt/java/jre/../lib/i386
            /opt/java/jre/lib/i386/client
            /opt/java/jre/lib/i386
            /usr/lib/xulrunner-devel-1.9.0.11
            /usr/lib/xulrunner-devel-1.9.0.11
            /usr/java/packages/lib/i386
            /lib
            /usr/lib
            

            但是当我设置 JVM 参数“-Djava.library.path=/tmp/”时,我只得到:

            /tmp/
            

            如果您手动设置 java.library.path,这可以解释为什么 ldd 在命令行中有效,但您的 .so 在 eclipse/java 中无效。

            您可以尝试不设置 java.library.path 并将 System.load 与库的绝对路径一起使用,而不是调用 System.loadLibrary。这可能允许 JVM 找到您的 .so 并在搜索其依赖项时仍使用默认路径。

            当然,如果这没有用,那么您也可以尝试在命令行中使用“-verbose:jni”打开 jni 调试输出。这可能会给你一些问题的线索。

            【讨论】:

              【解决方案6】:

              是的,LD_LIBRARY_PATH 对我有用

              【讨论】:

                【解决方案7】:

                添加这个答案可能会很有用在 AIX 机器中,我们需要设置 LIBPATH 环境变量而不是 LD_LIBRARY_PATH。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-11-28
                  • 2011-08-23
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-09-09
                  • 2010-11-04
                  • 1970-01-01
                  相关资源
                  最近更新 更多