在Tomcat8中重新加载应用程序期间,java.lang.UnsatisfiedLinkError本机库已加载到另一个类加载器中

时间:2018-11-23 10:10:19

标签: java java-native-interface tomcat8

我有一个在Tomcat8中运行的Java Web应用程序。 我将本机库存储在Tomcat安装的/ bin文件夹中。

我使用

用JNA加载库
Native.loadLibrary("myLib",MyLib.class);

如果我必须更新或重新加载它可以正常运行的应用程序,则可以正常工作。

我的问题是带有自己的本地库的第三方库。 我将其存储在相同的/ bin目录中,并且可以工作,但是当我重新加载应用程序Tomcat时,由于以下错误而无法加载:

java.lang.UnsatisfiedLinkError: Native Library ...already loaded in another classloader

如果我重新启动tomcat服务,它将再次起作用。我仅在重新加载应用程序时才发现此问题。

反编译第三方库时,我发现它的本机库已通过以下命令加载:

System.loadLibrary("thirdpartylib");

在重新加载应用程序的情况下,如何在没有UnsatisfiedLinkError的情况下强制在tomcat级别加载该库?

2 个答案:

答案 0 :(得分:1)

这实际上可能不是答案,但是评论太久了。

您读过about Tomcat classloader problems吗?这似乎正好符合您的问题。

如果那不能解决问题……您不知道(或不说)的是 other ClassLoader已经加载了本机库。这是Tomcat模块中的设置吗?如果可以,可以禁用它吗?

由于第三方要加载其自己的本机库,因此将很难解决。如果您查看System.loadLibrary()的源代码:

public static void loadLibrary(String libname) {
    Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
}

您可以看到它将使用调用类的ClassLoader,在这种情况下,它是第三方库的类。因此,要解决此问题,您需要将第三方库的ClassLoader与尝试首先加载本机库的ClassLoader对齐。您可以尝试enabling class loading trace并查找该第三方类何时加载,然后从那里备份以找到ClassLoader。

答案 1 :(得分:0)

尝试将您的myLib更改为其他名称,例如myLib_2,以避免冲突。

如果是相同的共享库,请尝试以下方法:

  

要使“正确的”类加载器加载本机库,您可以使用仅执行loadLibrary的单个静态方法创建一个微型类。将此类放在一个额外的jar中,然后将此jar放在共享的Tomcat目录中。然后在Web应用程序中,将对System.loadLibrary的调用替换为对新的静态方法的调用。这样,OpenCV类的类加载器及其本机库将匹配,并且可以初始化本机方法。

请参阅:https://stackoverflow.com/a/37213179/8034839