views:

346

answers:

2

I am using the recently released Glassfish v3 and while using native libraries glassfish would intermittently complain

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

The procedure to load native libraries in the previous glassfish release (v2.2) was to simply put the .dll files in GLASSFISH_HOME\lib. Now I dont know if there is such a magic folder in v3 and if there is do tell. I have also checked the admin screen and there are two variables I think are related to my problem: Native Library Path Prefix and Native Library Path Suffix. I have been scouring the internet to find an adequate description of what they do and how I should use them but apparently no-one likes to talk about them.

+1  A: 

First thing: a given native class can only be loaded into one class loader.

Second thing: each web app in a servlet container has its own class loader.

Third thing: you have to be very careful in coding native code to allow its classes to be garbage collected.

Result: once you load native code into a webapp, you are likely to get these errors if you try to unload and reload it.

I am, to some extent, skipping the really simple variation on this theme: simply loading two different webapps with the same native class.

Some folks prefer to load native code in the system class loader to stay out of this problem.

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

A native lib can only be loaded once in the JVM and you'll get that error message whenever you load a new version of the calling class (the class where the System.loadLibrary(String) call resides) on a redeploy. More on this below.

The procedure to load native libraries in the previous glassfish release (v2.2) was to simply put the .dll files in GLASSFISH_HOME\lib.

Well, this is actually only the first part of the story. To load a native library, you have of course to put it on the library path and to load it from the Java code. To do so, the convention is to include a static initializer like this:

class FooWrapper {
    static {
        System.loadLibrary("foo");
    }

    native void doFoo();
    }
}

Assuming you are working with a web application, a best practice is to not place the native libraries OR their JNI interfaces under WEB-INF/lib or WEB-INF/classes to avoid problems when reloading the application, as mentioned above. In other words, the class that calls System.loadLibrary(String) should be loaded by a classloader that is not affected by reloading the web application itself.

So my question is: where did you put that code?

PS: Another option would be to check if the dll is already available before to load it but I wouldn't do that.

Pascal Thivent