【问题标题】:UnsatisfiedLinkError: The library loads but I still get a link errorUnsatisfiedLinkError:库加载但我仍然收到链接错误
【发布时间】:2013-03-27 04:55:47
【问题描述】:

我有两个 Eclipse 插件:

  • plugin-1:为其他插件提供 .jar 包。 (C++ 库的 Java Wrapper)这个插件是通过点击 File->New->Other->Plug-in from Existing JAR Archives 创建的。

  • plugin-2:拥有plugin-1的本地库.so(Bundle-NativeCode指令在MANIFEST.MF中)并从plugin-1实例化一个类

(我实际上尝试将 .so 放在 plugin-1 中,但我似乎无法加载库,即使在包含 .so 的插件项目之外的 plugin-1 MANIFEST.MF 中使用 Bundle-NativeCode 指令也是如此。所以,所以我想我必须将 .so 与任何使用 plugin-1 的插件捆绑在一起。)

我正在从插件 2 运行 JUnit 测试,它从插件 2 实例化 MyClass,而插件 2 又从插件 1 实例化 MyLibraryClass。 MyClass 成功加载本机库并实例化 MyLibraryClass,而不会因加载本机库或实例化 MyLibraryClass 而引发 UnsatisfiedLinkError 或其他异常。在这种情况下,我没有运行插件——只是 JUnit 测试。

当我运行 plugin-2(使用产品配置)并实例化 MyClass 时,本机库加载正常,但当 MyClass 实例化 MyLibraryClass 时,我得到一个 UnsatisifiedLinkError。在这种情况下,我相信该库是根据我使用帖子How do I get a list of JNI libraries which are loaded?中描述的类获得的输出加载的@

注意:我使用的是 Eclipse 3.6.1。

这是一个代码示例,展示了我正在尝试做的事情的本质: 包 com.mylibrary;

import com.external_library.MyLibraryClass;


public class MyClass {


    public static void loadLibrary() {
      // Without Bundle-NativeCode in MANIFEST.MF I get 
      // "java.lang.UnsatisfiedLinkError: no mylibrary_java in java.library.path"
      System.loadLibrary("mylibrary_java"); // Loads libmylibrary_java.so. 

      // Works fine from JUnit Test
      // When I run the plugin, I get an UnsatisfiedLinkError:
      // "java.lang.UnsatisfiedLinkError: 
      // com.external_library.MyLibrary_javaJNI.new_MyLibraryClass__SWIG_3()J"
      MyLibraryClass instance = new MyLibraryClass(); 

    }
}

【问题讨论】:

  • 我有点困惑。如果我的理解正确,那么您有以下依赖链 [ 2
  • 也许您也可以发布一些您的 MyLibraryClass 的代码?
  • 1 不依赖于 2,但是任何使用 1 的人都在 1 中调用加载库方法。我只有一个 MyLibraryClass 的 .class 文件,但让我想想我可以给出什么代码你这将是值得的。我的意思是 JUnit,而不是 JUnit 插件。
  • @Tobias Willig -- 我修改了我的提交,希望能简化它并添加一点代码 sn-p。
  • 注意:我测试了这个新配置,我仍然看到同样的问题。

标签: java eclipse-plugin swig unsatisfiedlinkerror java-native-library


【解决方案1】:

我已经复制了您的设置,但遇到了同样的异常。

问题可以通过以下方式解决:

  • 将本机库添加到 plugin-1
  • 将 Bundle-NativeCode 指令添加到插件 1 的清单中
  • 在plugins-1的Activator的静态构造函数中加载库(可以自己写一个添加到插件中)

其他一些可能的错误来源: 请注意,对于任何具有本机绑定的类,永远不要更改包路径、类名和方法签名。否则 JNI 将无法找到本地对应项,并且您会收到 UnsatisfiedLinkError。在您的导入指令中,您指定了以下类名 com.external_library.MyLibraryClass,但您的错误消息具有不同的类名 com.external_library.MyLibrary_javaJNI。检查这些错误来源。

一些补充说明: 与 JUnit 插件测试相比,JUnit 测试不会启动 OSGi 环境。因此,您有一个带有普通 JUnit 测试的普通 Java 应用程序。如果您的本机库和您的应用程序包含在同一个文件夹(顶级)中,本机库将自动在 Windows 上找到。如果在 UNIX 系统上也是如此,那么这就是您的 JUnit 测试成功的原因。如果它位于不同的文件夹中,则必须为普通 Java 应用程序指定 Java 库路径。

MrMas 编辑: 通过将 .jar 文件添加到 plugin-2 来修改 plugin-2,使其不依赖于 plugin-1。

  1. 将 .jar 文件复制到 plugin-2 中。我把它和.so放在同一个目录中。
  2. 通过以下方式将 jar 添加到项目中:Project->Properties->Libraries->Add Jar
  3. 通过plugin.xml->Runtime->ClassPath section->Add将jar添加到类路径
  4. 从 Jar 中导出包(如果下游插件需要它们)
  5. 从plugin.xml->dependencies选项卡中移除plugin-1的依赖

现在您可以使用 System.loadLibrary 加载库,并使用插件内部和其他插件中的类。

我选择不修改 plugin-1,因为它是作为插件从现有 jar 创建的,我无法发现如何添加 Activator。相反,我选择了将 .jar 添加到 plugin-2 的路径。更多讨论请参见Adding jars to a Eclipse PlugIn。

【讨论】:

  • 我最初尝试按照您的描述进行操作,但无法为 Activator.java 文件创建新的 src 文件夹。我将编辑您的回复以填补漏洞,尽管您所描述的内容向我发送了正确的方向。感谢您抽出宝贵时间对此进行调查!
  • 是的。我很高兴能帮上忙。
【解决方案2】:

Bundle-NativeCode 是一个 OSGI 标记。这意味着只有 OSGI 类加载器在使用它。就我而言,我有一个 E4-RCP 应用程序。一个插件包含 Java 类。但是,我将本机代码放入一个片段中。

在加载和查找库时,OSGI 类加载器有一个片段列表(根据所涉及结构的命名)并使用类NativeCodeFinder 检查它们的Bundle-NativeCode。如果遇到问题,请尝试在相关功能处添加断点。 getNativePath() 返回 OSGIpart 读取的条目。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-06
    • 2020-12-25
    • 1970-01-01
    • 1970-01-01
    • 2014-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多