I have two Eclipse plugins:
plugin-1: provides a package in .jar to other plugins. (a Java Wrapper for a C++ library) This plugin was created by clicking File->New->Other->Plug-in from Existing JAR Archives.
plugin-2: has the native library .so for plugin-1 (Bundle-NativeCode
directive is in MANIFEST.MF) and instantiates a class from plugin-1
(I actually tried putting the .so in plugin-1, but I cannot seem to load the library, even with the Bundle-NativeCode directive in the plugin-1 MANIFEST.MF, outside of the plugin project that contains the .so, so I guess I have to bundle the .so with any plugin that uses plugin-1.)
I am running a JUnit tests from plugin-2 which instantiates MyClass
from plugin-2 which, in turn, instantiates MyLibraryClass
from plugin-1. MyClass
successfully loads the native library and instantiates MyLibraryClass
without an UnsatisfiedLinkError
or other exception being thrown from either the loading of the native library or from instantiating MyLibraryClass
. I am not running a plugin in this case -- just the JUnit tests.
When I run plugin-2 (using a product configuration) and instantiate MyClass
, the native library loads fine but I get an UnsatisifiedLinkError
when MyClass
instantiates MyLibraryClass
. In this case, I believe the library is being loaded based on the output I get from using the class described in the posting How do I get a list of JNI libraries which are loaded?
NOTE: I'm using Eclipse 3.6.1.
Here is a code sample that shows the essence of what I'm trying to do: package 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();
}
}
I have replicated your setup and I get the same exception.
The problem could be solved by:
Some other possible sources of errors: Be aware that the package path, the class name and the method signatures should never be changed for any class with native bindings. Otherwise JNI would not be able to find the native counterpart and you get an UnsatisfiedLinkError. In your import directive you specified the following classname com.external_library.MyLibraryClass, but your error message has a different classname com.external_library.MyLibrary_javaJNI. Check for these sources of errors.
Some additional explanations: A JUnit test in contrast to an JUnit plugin test starts no OSGi environment. Therefore you have a plain Java application with an ordinary JUnit test. If your native lib and your application are contained in the same folder (top level) the native lib will be automatically found on windows. If that is also true on UNIX systems, this would be an explanation why your JUnit test is successful. If it lies in a different folder, you have to specify the Java Library Path for an ordinary Java application.
EDIT by MrMas: Modify plugin-2 so it doesn't depend on plugin-1 by adding the .jar file to plugin-2.
Now you can load the library with a System.loadLibrary and use the classes from within the plugin and from another plugin.
I chose not to modify plugin-1 because it was created as a plugin from an existing jar to which I couldn't discover how to add an Activator. I instead chose the path of adding the .jar to plugin-2. See Adding jars to a Eclipse PlugIn for additional discussion.