Bhu*_*han 15 java java-native-interface tomcat opencv
我已经部署了一个Web应用程序,其中包含以下代码.
System.loadLibrary(org.opencv.core.Core.NATIVE_LIBRARY_NAME);
Run Code Online (Sandbox Code Playgroud)
现在,我部署了另一个也具有相同代码的Web应用程序.当它尝试加载库时,它会抛出以下错误.
Exception in thread "Thread-143" java.lang.UnsatisfiedLinkError:
Native Library /usr/lib/jni/libopencv_java248.so already loaded in
another classloader
Run Code Online (Sandbox Code Playgroud)
我想同时运行这两个应用程序.
直到现在我尝试过:
但上面没有一个工作,我可以做任何建议吗?
编辑:对于选项二,
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Run Code Online (Sandbox Code Playgroud)
这条线有效,但在我实际使用该库时会出现异常.那是我关注的时候
Mat mat = Highgui.imread("/tmp/abc.png");
Run Code Online (Sandbox Code Playgroud)
我得到了这个例外
java.lang.UnsatisfiedLinkError: org.opencv.highgui.Highgui.imread_1(Ljava/lang/String;)J
at org.opencv.highgui.Highgui.imread_1(Native Method)
at org.opencv.highgui.Highgui.imread(Highgui.java:362)
Run Code Online (Sandbox Code Playgroud)
use*_*253 13
问题在于OpenCV如何处理本机库的初始化.
通常,使用本机库的类将具有加载库的静态初始化程序.这样,类和本机库将始终加载到同一个类加载器中.使用OpenCV,应用程序代码加载本机库.
现在存在一个限制,即本机库只能在一个类加载器中加载.Web应用程序使用自己的类加载器,因此如果一个Web应用程序加载了本机库,则另一个Web应用程序不能执行相同操作.因此,加载本机库的代码不能放在webapp目录中,但必须放在容器的(Tomcat)共享目录中.如果你有一个用上面常用模式编写的类(loadLibrary在使用类的静态初始化程序中),那么将包含该类的jar放在共享目录中就足够了.loadLibrary但是,使用OpenCV和Web应用程序代码中的调用,本机库仍将加载到"错误的"类加载器中,您将获得UnsatisfiedLinkError.
为了使"正确的"类加载器加载本机库,您可以使用单个静态方法创建一个小类,仅执行loadLibrary.将此类放在一个额外的jar中,并将此jar放在共享的Tomcat目录中.然后在Web应用程序中,将调用替换System.loadLibrary为对新静态方法的调用.这样,OpenCV类的类加载器及其本机库将匹配,并且可以初始化本机方法.
编辑:评论者要求的示例
代替
public class WebApplicationClass {
static {
System.loadLibrary(org.opencv.core.Core.NATIVE_LIBRARY_NAME);
}
}
Run Code Online (Sandbox Code Playgroud)
使用
public class ToolClassInSeparateJarInSharedDirectory {
public static void loadNativeLibrary() {
System.loadLibrary(org.opencv.core.Core.NATIVE_LIBRARY_NAME);
}
}
public class WebApplicationClass {
static {
ToolClassInSeparateJarInSharedDirectory.loadNativeLibrary();
}
}
Run Code Online (Sandbox Code Playgroud)