简体   繁体   中英

Shared JNI library (.so) in Tomcat - UnsatisfiedLinkError

I have a JNI library (.so) shared between two web applications deployed in Tomcat7. I am loading the library using the System.loadLibrary only once in the first web application that is being deployed and then in the second I'm checking if it already was loaded to not load anymore (I tried loading it in both and I got UnsatisfiedLinkError - library was loaded by another classloader). I can make any call to the native library in the first application, but in the second one I get UnsatisfiedLinkError with the method name that I am trying to call.

I am running out of ideas of what I can do. Any ideas? I tried most of the solutions on SO. Thank you.

EDIT Yes, I tried adding the library in the tomcat lib folder and loading it from there. Initially it was in the bin folder and the same issue occurs.

Yes, this will happen when you try to load the library that has already loaded my another web application. Tomcat, uses separate class loaders for each of the web application, and it wont allow you load a same native library more than once to JVM via another class loader

Move any share jar files if any that consumes JNI from you sharedlib.so. Add the system path to sharedlib ,

export LD_LIBRARY_PATH=/path/to/whereyourlinklibrary

Write a simple class like this which enables you to load your shared library when tomcat starts. Just compile this class and drop it in tomcat lib folder

package msm;
public class DLLBootstrapper {

     static {
      System.loadLibrary("sharedlib");
     }

     public static void main(String args[]) {
      System.out.println("Loaded");
     }

    }

you can now load this class from any of your web application ( probably in startup listener)

Class.forName("msm.DLLBootstrapper");

Good to go!

您是否尝试将共享JNI库放在server的lib目录中。它应该由所有部署的Web应用程序共享。

You need to load any native code from within the server classloader and not the webapp classloader. I recommend to write a Listener which loads the binary image of the shared object into the VM. This will happens only once. Please see the AprLifecycleListener on how to properly do that. It included a JNI compnent which likely represents you case exactly.

The shared object has to reside in ${catalina.home}/lib and LD_LIBRARY_PATH hat to point to it.

Tomcat has a built-in solution for this issue as of versions 9.0.13, 8.5.35, and 7.0.92:

1) Use the JniLifecycleListener to load the native library.

2) Use the loadLibrary() or load() from org.apache.tomcat.jni.Library instead of System.

See more details and examples in my answer at java.lang.UnsatisfiedLinkError: Native Library XXX.so already loaded in another classloader

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM