最近做了一个识别答题卡功能的项目,放在Tomcat下,偶尔就会报java.lang.UnsatisfiedLinkError: Native Library C:\Program Files\Java\jdk1.8.0_201\bin\opencv_java341.dll already loaded in another classloader。
经过排查,是把war包放入Tomcat/webapps目录下时,没重启Tomcat,而是让Tomcat自动重启war包导致。
原因是源代码中有静态方法:
import org.opencv.core.Core; //...... static { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); }而UnsatisfiedLinkError错误表明jopencv_java341.dll已经被JVM的ClassLoader load了。通过查阅资料发现 Web Server的自动重启机制是产生这一问题的根源。当tomcat重启包含opencv的这个Web应用时,会因为包含静态类的语句而自动执行 opencv的加载。但重启Web应用并不是重启整个tomcat(即:上一次启动的JVM仍然存在),也就是说OpenCV已经被加载过了,因此系统将抛出UnsatisfiedLinkError错误。而当我们手工重启Tomcat时,则会将上一次启动的JVM关闭并重新启动,这时会正常加载opencv。
Java API 表明:JVM只允许一个默认的ClassLoader来load native library,同时并不提供专门的API来unload一个 loaded native library,因此无法在我们的重启Web应用的代码中来手工清除已经load的opencv。
也有推荐如下2种方法解决,自己测试后仍然报错,方法先留着,有时间再研究下。
1.使用try catch
static { try { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); } catch (UnsatisfiedLinkError ignore) { //使用spring-dev-tools之后,上下文会被加载多次,所以这里会抛出链接库已被加载的异常。 //有这个异常则说明链接库已被加载,直接吞掉异常即可 } }2.将opencvXXX.jar放入Tomcat/lib目录下
参考链接:
https://blog.csdn.net/xiyouzhanglong/article/details/83598109
https://blog.csdn.net/qq_29753285/article/details/87873350