Tomcat的Release Notes 里有这么一段话:
=======================
JNI Based Applications:
=======================
Applications that require native libraries must ensure that the libraries have
been loaded prior to use. Typically, this is done with a call like:
static {
System.loadLibrary("path-to-library-file");
}
in some class. However, the application must also ensure that the library is
not loaded more than once. If the above code were placed in a class inside
the web application (i.e. under /WEB-INF/classes or /WEB-INF/lib), and the
application were reloaded, the loadLibrary() call would be attempted a second
time.
To avoid this problem, place classes that load native libraries outside of the
web application, and ensure that the loadLibrary() call is executed only once
during the lifetime of a particular JVM.
简单地说就是JNI库的加载在启动Tomcat的JVM中只能进行一次,如果两次执行System.loadLibrary("path-to-library-file");将会导致错误(Error,不是Exception):
java.lang.UnsatisfiedLinkError: Native Library xxx.dll already loaded in another classloader。
可是这段话并没有给出具体的解决办法。我要使用的一个NT登录验证的JAAS模块碰到了这个问题:我把包含这个语句的库放在了某个web应用程序的lib目录下,结果当修改了某个web配置文件导致这个程序的context reload时,JAAS模块就不能使用,因为它又重新加载JNI库导致错误。只有重新启动整个tomcat才能恢复正常,十分麻烦。
找了好久,终于在一个大侠的文章(http://cuiyingfeng.blog.ccidnet.com/blog/ccid/do_showone/tid_48232.html)中找到了解决方法:
1、加载JNI库的包放在Tomcat的common/lib目录下,而不要放在各context的lib目录下;
2、每次加载JNI库之前检查是否已经加载过。
由于加载语句不是我能控制的,所以第二种方法不能实现,于是我就通过第一种方法把这个问题解决了。