2

Following this question.
I'm using Bundle-NativeCode header to specify native libraries that should be loaded by plugin.
It works fine when the libraries reside in the same plugin as the code that loads them (System.loadLibrary). However, when I try to put the libraries in a separate plugin fragment, System.loadLibrary fails with UnsatisfiedLinkError.

The manifest of the host plugin (when the libraries in the host plugin):

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Jni
Bundle-SymbolicName: com.ebar.workmode.jni
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.ebar.workmode.jni.Activator
Bundle-Vendor: EBAR
Require-Bundle: org.eclipse.core.runtime,
 org.slf4j.api,
 javax.inject;bundle-version="1.0.0",
 com.ebar.workmode.contracts;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
Export-Package: com.ebar.workmode.jni
Eclipse-ExtensibleAPI: true
Bundle-NativeCode: native/ipcs.dll ; native/ipcs_tcpip_plugin.dll ; osname=win32

The manifest of the plugin fragment:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: workmode JNI win x86
Bundle-SymbolicName: com.ebar.workmode.jni.windows.x32;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: EBAR
Fragment-Host: com.ebar.workmode.jni;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-NativeCode: native/ipcs_tcpip_plugin.dll ; native/ipcs.dll ; osname=win32

Activator.start of the host plugin:

@Override
public void start(BundleContext bundleContext) throws Exception { 
        System.loadLibrary("ipcs");      
        System.loadLibrary("ipcs_tcpip_plugin");            
}

The error that I get when I remove the Bundle-NativeCode header from the host plugin:

java.lang.UnsatisfiedLinkError: no ipcs in java.library.path
    at java.lang.ClassLoader.loadLibrary(Unknown Source)
    at java.lang.Runtime.loadLibrary0(Unknown Source)
    at java.lang.System.loadLibrary(Unknown Source)
    at com.ebar.workmode.jni.Activator.start(Activator.java:34)
    at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:771)
    at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:1)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:764)
    ... 102 more
  • The plugin fragment is added to the product
  • The plugin fragment doesn't show any error in target platform state tab
  • The native folder of plugin fragment is included in binary build (in build.properties)

Why isn't it working and how to make the host plugin to load the native libraries from the plugin fragment? Or alternatively, is there a way to make the plugin fragment to load its libraries?

Community
  • 1
  • 1
JeB
  • 11,653
  • 10
  • 58
  • 87
  • Looks similar to this: http://stackoverflow.com/q/12912772/2670892 – greg-449 Mar 15 '16 at 16:57
  • Looks pretty different to me... I don't have multiple fragments at the moment. All I'm trying to do (as a first step) is moving Windows libraries to plugin fragment. – JeB Mar 15 '16 at 17:14
  • Are you sure the fragment is attached? The host has `Bundle-Version: 1.0.0.qualifier` while the fragment's `Fragment-Host` has `bundle-version="1.0.0"`. Version 1.0.0 is not equal to 1.0.0.qualifier. So I think perhaps the fragment is not attached to the host which is why the host could not find the native code. – BJ Hargrave Mar 15 '16 at 22:09
  • I think the bundle-version in fragment specifies the minimal version, so that 1.0.0.qualifier should match. Besides, I've tried the same without specifying the bundle version in fragment. Anyways, is there a way I can check whether the fragment is attached to host? – JeB Mar 15 '16 at 22:12
  • The spec seems to not merge the Bundle-NativeCode header. (See OSGi Core R6 3.14) Since you've defined it in both the host and the fragment I expect the framework only uses the host's version. This does not match the error ... you report an exception on the DLL in the host. (This also seems to indicate that it is not the attachment.) Anyway, you could try to put the header just in the host or fragment? – Peter Kriens Mar 18 '16 at 10:43
  • That's what I'm doing. When I don't use fragment (the case that works for me), I put `Bundle-NativeCode` in the host. When I do use the fragment, I remove `Bundle-NativeCode` from the host and put it in the fragment. – JeB Mar 18 '16 at 11:35

0 Answers0