UnsatisfiedLinkError:库加载但我仍然收到链接错误

时间:2013-04-04 22:13:52

标签: java eclipse-plugin unsatisfiedlinkerror nativelibrary

我有两个Eclipse插件:

  • plugin-1:将.jar中的包提供给其他插件。 (用于C ++库的Java Wrapper)此插件是通过单击File-> New-> Other-> Plug from in Existing JAR Archives创建的。

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

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

我正在从plugin-2运行JUnit测试,它从plugin-2实例化MyClass,然后从插件-1中实例化MyLibraryClassMyClass成功加载本机库并实例化MyLibraryClass,而不会在加载本机库或实例化UnsatisfiedLinkError时抛出MyLibraryClass或其他异常。在这种情况下我没有运行插件 - 只是JUnit测试。

当我运行plugin-2(使用产品配置)并实例化MyClass时,本机库加载正常,但在UnsatisifiedLinkError实例化MyClass时我得到MyLibraryClass。在这种情况下,我相信库是根据我使用发布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 个答案:

答案 0 :(得分:1)

我已经复制了你的设置,我得到了同样的例外。

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

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

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

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

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

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

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

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

答案 1 :(得分:1)

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

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