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 开发者_如何学Gothere 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.
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.
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.
精彩评论