Tomcat中的共享JNI库(.so) - UnsatisfiedLinkError

时间:2016-10-14 13:01:24

标签: java tomcat web-applications java-native-interface shared-libraries

我在Tomcat7中部署的两个Web应用程序之间共享了一个JNI库(.so)。我在部署的第一个Web应用程序中只使用System.loadLibrary加载一次库,然后在第二个我正在检查它是否已经加载到不再加载(我尝试在两者中加载它和我得到UnsatisfiedLinkError - 库由另一个类加载器加载)。我可以在第一个应用程序中对本机库进行任何调用,但在第二个应用程序中,我使用我要调用的方法名称获取UnsatisfiedLinkError。

我的想法已经用完了。有任何想法吗?我在SO上尝试了大部分解决方案。 谢谢。

修改 是的,我尝试在tomcat lib文件夹中添加库并从那里加载它。最初它位于bin文件夹中,同样的问题也出现了。

4 个答案:

答案 0 :(得分:2)

是的,当您尝试加载已加载我的另一个Web应用程序的库时,会发生这种情况。 Tomcat为每个Web应用程序使用单独的类加载器,它不允许您通过另一个类加载器多次向JVM加载相同的本机库

移动任何共享jar文件(如果有的话)从您的sharedlib.so中消耗JNI。将系统路径添加到sharedlib,

export LD_LIBRARY_PATH=/path/to/whereyourlinklibrary

编写一个这样的简单类,使您可以在tomcat启动时加载共享库。只需编译该类并将其放在tomcat lib文件夹

package msm;
public class DLLBootstrapper {

     static {
      System.loadLibrary("sharedlib");
     }

     public static void main(String args[]) {
      System.out.println("Loaded");
     }

    }

您现在可以从任何Web应用程序(可能在启动侦听器中)加载此类

Class.forName("msm.DLLBootstrapper");

很高兴去!

答案 1 :(得分:0)

您是否尝试将共享JNI库放在server的lib目录中。它应该由所有部署的Web应用程序共享。

答案 2 :(得分:0)

您需要从服务器类加载器中加载任何本机代码,而不是webapp类加载器。我建议写一个previewFile(path [,displayname]),它将共享对象的二进制映像加载到VM中。这只会发生一次。有关如何正确执行此操作,请参阅AprLifecycleListener。它包括一个JNI组件,它可能完全代表你的情况。

共享对象必须驻留在Listener${catalina.home}/lib帽子中才能指向它。

答案 3 :(得分:0)

Tomcat从版本9.0.13、8.5.35和7.0.92开始具有针对此问题的内置解决方案:

1)使用JniLifecycleListener加载本机库。

2)使用org.apache.tomcat.jni.Library中的loadLibrary()或load()代替System。

java.lang.UnsatisfiedLinkError: Native Library XXX.so already loaded in another classloader的答案中查看更多详细信息和示例