在OSGi包中加载DLL(使用JNA)

时间:2009-09-03 19:48:08

标签: java osgi jna

OSGi无法找到我的DLL文件,我似乎无法弄清楚原因。

目前我在我的捆绑包的根目录下有DLL文件(foo.dll),我也尝试在libs目录中使用它。

有问题的捆绑包的清单看起来像这样:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: foobundle
Bundle-SymbolicName: com.foo.bar
Bundle-Version: 1.0.0
Bundle-Vendor: me
Import-Package: com.sun.jna,
 com.sun.jna.ptr,
 com.sun.jna.win32
Export-Package: com.foo.bar
Bundle-NativeCode: foo.dll;
 osname=WindowsXP;
 processor=x86

然后在我的JNA界面中执行loadLibrary(根据文档):

public interface MyFooInterface extends com.sun.jna.Library{
    static final MyFooInterface INSTANCE = (MyFooInterface)com.sun.jna.Native.loadLibrary("foo", MyFooInterface .class);

    // specific interface defs here...
}

然后在另一个类中我尝试使用JNA接口

// ...code
int var = MyFooInterface.INSTANCE.bar();
// ...more code

我通过另一个包(导出com.sun.jna和上面导入的其他包)提供了JNA,但是也尝试用这里定义的包打包它(在这种情况下将它添加到类路径中等等)。 )。

我也尝试过指定Bundle-NativeCode: /foo.dll

同样有趣的是,这些是相关的OSGi属性(我使用getprop提取的)

org.osgi.framework.os.name=WindowsXP
org.osgi.framework.processor=x86

即使在所有这些(以及我所做的每一次试验)之后,我总是会遇到以下错误(并且未显示堆栈跟踪):

java.lang.UnsatisfiedLinkError: Unable to load library 'foo': The specified module could not be found.

...所以我错过了什么?

编辑:我还应该注意到我已经测试并成功了JNA接口代码和它作为JUnit测试程序的一部分进行对话的DLL。

编辑2 :将此代码添加到调用库的类似乎允许JNA查找库(稍后调用Native.loadLibrary时)。看来我应该能够根据Manifest中的Bundle-NativeCode指令来避免这个调用。很明显,一旦加载了库,Native.loadLibrary会抓取它的现有实例,但我不想依赖于这种特定于订单的策略。

static{
    System.loadLibrary("foo");
}

3 个答案:

答案 0 :(得分:7)

问题是专门的JNA loadLibrary调用,它不支持OSGi。当您从OSGi包调用loadLibrary时,它将使用OSGi类加载器(可识别bundle)来查找DLL的位置,在这种情况下,从包中提取它并通过System.loadLibrary()使其可加载打电话到特定地点。

由于这个JNA似乎是(a)不是OSGi意识,而且(b)超级,为什么不直接使用System.loadLibrary()?

如果你需要同时写两个,那么在BundleActivator的bundle的start()方法中执行System.loadLibrary(),这将带来本机库(你可能想确保它无法加载,捆绑无法在任何情况下启动。)

答案 1 :(得分:1)

查看JNA的文档,它声明:

  • 使您的目标库可用于Java程序。有两种方法可以做到这一点:
    • 首选方法是将jna.library.path系统属性设置为目标库的路径。此属性类似于java.library.path,但仅适用于JNA加载的库。
    • 在启动VM之前更改相应的库访问环境变量。这在Windows上为PATH,在Linux上为LD_LIBRARY_PATH,在OSX上为DYLD_LIBRARY_PATH

因此,为了解决这个缺点,你可以解决库的绝对路径并加载它。

假设它是Eclipse的标准类加载器,你可以执行ClassLoader.findLibrary(),它应该在bundle中找到本地库。

答案 2 :(得分:0)

我建议您尝试将dll打包为jar:

jar cvf foo.dll.jar foo.dll

并将jar加载为常规库。

相关问题