Tobia
Tobia

Reputation: 9526

java.lang.UnsatisfiedLinkError Native Library already loaded in another classloader during app reload in Tomcat8

I have a Java Web application running in Tomcat8. I stored the native libraries in /bin folder of Tomcat installation.

I load libraries with JNA using

Native.loadLibrary("myLib",MyLib.class);

This works without any problem, if I have to update or reload the application it works.

My problem is a third-party library with its own native library. I stored it in the same /bin directory and it works, but when I reload the application Tomcat fails to load with this error:

java.lang.UnsatisfiedLinkError: Native Library ...already loaded in another classloader

If I restart tomcat service it works again. I found this problem only during the application reload.

Decompiling the third-party library I found that its native library is loaded with this command:

System.loadLibrary("thirdpartylib");

How can I force this library load at tomcat level without a UnsatisfiedLinkError in case of application reload?

Upvotes: 0

Views: 5641

Answers (2)

Wheezil
Wheezil

Reputation: 3462

This may not actually be an answer, but it is too long for a comment.

Have you read about Tomcat classloader problems? That seems to precisely match your issue.

If that doesn't solve it... what you don't know (or don't say) is what other ClassLoader has already loaded the native library. Is this a setting in Tomcat modules, and if so can you disable that?

Since the third party wants to load its own native library, this is going to be hard to work around. If you look at the source for System.loadLibrary():

public static void loadLibrary(String libname) {
    Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
}

You can see that it is going to use the ClassLoader of the calling class, which in this case is the class of the third-party library. So to solve this you need to align the ClassLoader of the third-party lib with the ClassLoader of what tries to load the native library first. You could try enabling class loading trace and look for when that third-party class is loaded, and back up from there to find the ClassLoader.

Upvotes: 2

shizhen
shizhen

Reputation: 12583

Try to change your myLib to another name, e.g. myLib_2, to avoid conflicts.

If it is the same shared library, try below approach:

To make the "right" class loader load the native library you could create a tiny class with a single static method doing only the loadLibrary. Put this class in an extra jar and put this jar in the shared Tomcat directory. Then in the web applications replace the call to System.loadLibrary with a call to your new static method. This way the class loaders for the OpenCV classes and their native library will match and the native methods can be initialized.

See: https://stackoverflow.com/a/37213179/8034839

Upvotes: 0

Related Questions