如何使用OSGi片段来提供具有相同文件名的依赖于平台的本机代码?

我正在使用JNotify项目来监听文件系统事件。 这取决于每个操作系统的一个本机库:处理器架构。 例如,有一个用于Windows x86的库,一个用于x86-64等的库。

整体捆绑

最初,我有一个包含JNotify Java类和本机代码的包。 本机代码在Bundle-NativeCode中声明如下:

(我已经将这些格式化为bnd样式以获得更好的可读性……显然,实际的MANIFEST.MF文件已正确形成)。

Bundle-NativeCode: jnotify_64bit.dll;osname=Win32;osname="Windows NT (unknown)";osname = WindowsXP;osname = Windows2000;osname = Windows2003;osname = WindowsVista;osname = Windows7;osname = WindowsServer2008;osname= Windows8;osname = WindowsServer2012;processor = x86-64,\ jnotify.dll;osname=Win32;osname="Windows NT (unknown)";osname = WindowsXP;osname = Windows2000;osname = Windows2003;osname = WindowsVista;osname = Windows7;osname = WindowsServer2008;osname = Windows8;osname = WindowsServer2012;processor = x86,\ libjnotify.so;osname = Linux;processor = x86,\ libjnotify64.so;osname = Linux;processor = x86-64,\ libjnotify.dylib;osname = Mac OSX;processor = x86;processor = x86-64,\ * 

这很好用。

转移到片段

我认为如果我将库移动到单独的片段包中会很“好”,这样我就可以为我感兴趣的体系结构贡献片段。以Linux为例,我将它们分成两个包:

Linux 32位

 Include-Resource: lib/libjnotify.so Bundle-NativeCode: libjnotify.so;osname = Linux;processor = x86,\ * Fragment-Host: net.contentobjects.jnotify Bundle-Version: 0.94.0 

Linux 64位

 Include-Resource: lib/libjnotify.so Bundle-NativeCode: libjnotify.so;osname = Linux;processor = x86-64,\ * Fragment-Host: net.contentobjects.jnotify Bundle-Version: 0.94.0 

请注意,这些捆绑包是根据不同的来源构建的。 虽然libjnotify.so文件名是相同的,但它们是不同Eclipse项目中的不同文件。 它们必须与JNotify一样。

请注意,相同的文件名将提供给主机包。 在这种情况下,文件名是libjnotify.so。

如果我在我的64位机器上运行这些,并且 32位之前加载64位软件包,它就可以工作。

但是,如果首先加载32位包,我得到:

 Couldn't initialise JNotify: java.lang.UnsatisfiedLinkError: /blah/generated/fw/bundle46/version0.0/net.contentobjects.jnotify.linux.x86-0.94.0.jar-lib/0/libjnotify.so: /blah/generated/fw/bundle46/version0.0/net.contentobjects.jnotify.linux.x86-0.94.0.jar-lib/0/libjnotify.so: wrong ELF class: ELFCLASS32 (Possible cause: architecture word width mismatch) (JnotifyFileSystemObserver.java:53, thread platformExecutor) 

显然正在加载32位库。 但为什么? My Bundle-NativeCode定义主机必须是32位Linux机器才能使用32位软件包的版本。 我想如果那个子句不匹配,库会被忽略吗?

东西我试过了

  • 删除可选的通配符…这只是意味着捆绑包无法解析

由于您的片段占用相同的资源名称空间,因此只能访问一个.so文件。 您只能部署一个片段,或者您可以尝试将它们放在不同的目录中:

  Fragment 32-bit: Include-Resource: x32/libjnotify.so=lib/libjnotify.so Fragment 64-bit: Include-Resource: x64/libjnotify.so=lib/libjnotify.so 

我还认为你需要将Bundle-NativeCode标头放在主机包中并引用正确的目录,因为我认为这个标头没有在主机中合并。

检查您运行的Eclipse / OSGi容器的版本。 我怀疑你发现你正在启动的容器已经设置为32位系统。

如果您不介意限制使用Equinox ,则可以在Eclipse-PlatformFilter使用每个片段一个片段的解决方案。 在这种情况下,只能在任何时候解析和安装一个具有本机代码的片段,从而避免命名空间冲突。