我有一个在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级别加载该库?
答案 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类的类加载器及其本机库将匹配,并且可以初始化本机方法。