当前位置: 首页 > 面试题库 >

java.lang.UnsatisfiedLinkError:本机库XXX.so已加载到另一个类加载器中

欧阳智志
2023-03-14
问题内容

我已经部署了一个Web应用程序,其中包含以下代码。

System.loadLibrary(org.opencv.core.Core.NATIVE_LIBRARY_NAME);

现在,我部署了另一个具有相同代码的Web应用程序。尝试加载库时,将引发以下错误。

Exception in thread "Thread-143" java.lang.UnsatisfiedLinkError: 
Native Library /usr/lib/jni/libopencv_java248.so already loaded in
another classloader

我想同时运行这两个应用程序。

直到现在我已经尝试了:

  1. 在一个应用程序中加载库,并将上述异常捕获到另一个应用程序中
  2. 从两个应用程序中删除了jar,并将opencv.jar放入Tomcat的类路径(即/ usr / share / tomcat7 / lib中)。

但是以上方法均无效,我可以通过任何建议做到这一点?

编辑: 对于选项二,

System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

这行有效,但是在我实际要使用该库时会出现异常。那是当我跟随

Mat mat = Highgui.imread("/tmp/abc.png");

我得到这个例外

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)

问题答案:

问题在于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);
    }
}

采用

public class ToolClassInSeparateJarInSharedDirectory {
    public static void loadNativeLibrary() {
        System.loadLibrary(org.opencv.core.Core.NATIVE_LIBRARY_NAME);
    }
}

public class WebApplicationClass {
    static {
        ToolClassInSeparateJarInSharedDirectory.loadNativeLibrary();
    }
}


 类似资料:
  • 我已经部署了一个Web应用程序,其中包含以下代码。 现在,我部署了另一个也有相同代码的Web应用程序。当它试图加载库时,它抛出以下错误。 我想同时运行这两个应用程序。 null 我得到了一个例外

  • 我有两个java web应用程序,需要使用Windows集成身份验证连接到SQL Server数据库。 加载的第一个可以正常工作,但第二个会引发异常: 当我放置sqljdbc\u auth时,就会出现上述错误。其中一个文件夹中的dll: C:\WINDOWS\system 32\ C:\Program Files\Apache Software Foundation\Tomcat 7.0\bin\

  • 我正在我的web应用程序中集成一个web服务。web服务为我提供了一个。dll和。jar文件。我把.dd放在/jre/bin中,把.jar放在/jre/lib中,然后开发代码并部署应用程序。在开发过程中,我还将。jar文件包含在我的项目构建路径中。在tomcat中运行它时,它给了我一个错误:

  • 如果认为Tomcat的公共类加载器正在加载这个类,实例化它(按照:http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html),然后将引用传递给webapp,从而绕过webapp类加载器,这是不是错的? 是否有一种方法可以告诉Tomcat实例化我的单例(强制公共类加载程序执行),然后提供该实例来满足我的WebApp的依赖性? 任何

  • 我有一个类,它实现了接口。类由system classloader加载,接口在第三方组件中定义,我认为第三方组件将接口加载到另一个类加载器(动态类加载器)中。 当我试图创建的新实例时,我得到的是的。我想这是因为它是由不同的类加载器加载的。 我尝试创建(与Guice使用的类似),然后从system类加载器加载类,并从另一个类加载器加载所有其他类,我认为这是用于的类加载器,但没有成功。 有办法绕过它吗

  • 问题内容: 我使用Maven 将其包含在我的项目中,并将Ghostscript安装到。 但是我仍然会出错 。 我添加到位于“ gsdll64.dll”(即)所在的env变量目录中。还尝试使用启动应用程序。 但是我总是得到(但是当我使用JVM参数启动时,我得到了异常(Eclipse找不到Main类,但是当我启动我的应用程序时,我手动将Eclipse指向Main类))/ 问题答案: 如果复制到工作目录