UnsatisfiedLinkError: the library is loading, but I still get the error message

I have two Eclipse plugins:

  • plugin-1: provides a package in .jar for other plugins. (Java Wrapper for C ++ library). This plugin was created by clicking File-> New-> Other-> Plug-in from existing JAR archives.

  • plugin-2: has a built-in .so library for plug-1 (the Bundle-NativeCode is in MANIFEST.MF) and creates an instance of the class from plug-1

(I really tried putting .so in plugin-1, but I canโ€™t load the library, even with the Bundle-NativeCode directive in plugin-1 MANIFEST.MF, outside of the plugin project that contains. So I think I need to link .so with any plugin that uses plugin-1.)

I run JUnit tests from plugin-2, which creates an instance of MyClass from plugin-2, which in turn creates MyLibraryClass from plugin-1. MyClass successfully loads its own library and creates an instance of MyLibraryClass without an UnsatisfiedLinkError or other exception that is created from loading its own library or from an instance of MyLibraryClass . In this case, I do not run the plugin - just JUnit tests.

When I run plugin-2 (using the product configuration) and create an instance of MyClass , the native library loads fine, but I get UnsatisifiedLinkError when MyClass creates an instance of MyLibraryClass . In this case, I believe that the library is loading based on the result that I get from using the class described in the publication. How do I get a list of JNI libraries to load?

NOTE. I am using Eclipse 3.6.1.

Here is an example of code that shows the essence of what I'm trying to do: com.mylibrary package;

 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(); } } 
+1
source share
2 answers

I have replicated your setup and I am getting the same exception.

The problem can be solved with:

  • add native library to plugin-1
  • add the Bundle-NativeCode directive to the plugin-1 manifest
  • load the library into the static constructor of the plug-in activator-1 (you can write one and add it to the plug-in)

Some other possible sources of errors: Keep in mind that the package path, class name and method signatures should never be changed for any class with its own bindings. Otherwise, JNI will not be able to find the native copy, and you will get UnsatisfiedLinkError. In the import directive, you specified the following class name com.external_library.MyLibraryClass, but your error message has a different class name com.external_library.MyLibrary_javaJNI. Check out these sources of errors.

Additional explanations: The JUnit test, unlike the JUnit plug-in test, does not start the OSGi environment. Therefore, you have a simple Java application with the usual JUnit test. If your native lib and your application are contained in the same folder (top level), the native lib will be automatically found in the windows. If this is true for UNIX systems, this will explain why your JUnit test is successful. If it is in a different folder, you must specify the Java library path for a regular Java application.

EDIT MrMas: Modify plugin-2 so that it does not depend on plugin-1 by adding the .jar file to plugin-2.

  • Copy the .jar file to plugin-2. I put it in the same directory as .so.
  • Add the jar to the project through: Project-> Properties-> Libraries-> Add Jar
  • Add jar to class path through plugin.xml-> Runtime-> ClassPath section-> Add
  • Export packages from Jar (if needed for downstream plugins)
  • Remove the plugin-1 dependency on the plugin.xml tab->

Now you can load the library using System.loadLibrary and use the classes from the plugin and from another plugin.

I decided not to modify plug-1, because it was created as a plug-in from an existing can, to which I could not learn how to add an activator. Instead, I chose the path to add .jar to plugin-2. See Adding Banners to the Eclipse Plugin for more discussion.

+1
source

Bundle-NativeCode is an OSGI tag. This means that only OSGI class loaders are used. In my case, I had an E4-RCP application. One plugin contains a Java class. However, I put my own code in a snippet.

When loading and searching the library, the OSGI class loader has a list of fragments (according to the name of the corresponding structure) and considers their Bundle-NativeCode using the NativeCodeFinder class. If you have problems, try adding breakpoints to the appropriate functions. getNativePath() returns entries as read by OSGIpart.

+1
source

Source: https://habr.com/ru/post/954698/


All Articles