javaeclipse-pluginswigunsatisfiedlinkerrorjava-native-library

UnsatisfiedLinkError: The library loads but I still get a link error


I have two Eclipse plugins:

(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(); 

    }
}

Solution

  • 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.

    1. Copy the .jar file into plugin-2. I put it in the same directory as the .so.
    2. Add the jar to the project via: Project->Properties->Libraries->Add Jar
    3. Add the jar to the class path via plugin.xml->Runtime->ClassPath section->Add
    4. Export the packages from the Jar (if they're needed by downstream plugins)
    5. Remove the dependence of plugin-1 from the plugin.xml->dependencies tab

    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.