Tomcat 中的共享 JNI 库 (.so) - UnsatisfiedLinkError
Shared JNI library (.so) in Tomcat - UnsatisfiedLinkError
我有一个在 Tomcat7 中部署的两个 Web 应用程序之间共享的 JNI 库 (.so)。我在第一个正在部署的 Web 应用程序中仅使用 System.loadLibrary 加载库一次,然后在第二个中我检查它是否已经加载以不再加载(我尝试在两者中加载它并且我得到 UnsatisfiedLinkError - 库被另一个类加载器加载)。我可以在第一个应用程序中对本机库进行任何调用,但在第二个应用程序中,我得到 UnsatisfiedLinkError 以及我尝试调用的方法名称。
我运行不知道自己能做什么。有任何想法吗?我在 SO 上尝试了大部分解决方案。
谢谢。
编辑
是的,我尝试在 tomcat lib 文件夹中添加库并从那里加载它。最初它在 bin 文件夹中,但出现了同样的问题。
您是否尝试过将共享 JNI 库放在 server.It 的 lib 目录中应该由所有部署的 Web 应用程序共享。
您需要从服务器类加载器而不是 webapp 类加载器中加载任何本机代码。我建议编写一个 Listener
将共享对象的二进制映像加载到 VM 中。这只会发生一次。请参阅 AprLifecycleListener
以了解如何正确执行此操作。它包括一个 JNI 组件,它可能完全代表您的情况。
共享对象必须驻留在 ${catalina.home}/lib
和 LD_LIBRARY_PATH
帽子中才能指向它。
是的,当您尝试加载已加载我的另一个 Web 应用程序的库时,会发生这种情况。 Tomcat,为每个 Web 应用程序使用单独的 class 加载器,它不允许您通过另一个 class 加载器
将同一个本地库多次加载到 JVM
移动任何共享 jar 文件,如果有任何消耗您的 JNI sharedlib.so。将系统路径添加到 sharedlib ,
export LD_LIBRARY_PATH=/path/to/whereyourlinklibrary
像这样写一个简单的 class,这样您就可以在 tomcat 启动时加载您的共享库。只需编译此 class 并将其放入 tomcat lib 文件夹
package msm;
public class DLLBootstrapper {
static {
System.loadLibrary("sharedlib");
}
public static void main(String args[]) {
System.out.println("Loaded");
}
}
您现在可以从您的任何 Web 应用程序(可能在启动侦听器中)加载此 class
Class.forName("msm.DLLBootstrapper");
干得好!
Tomcat 从版本 9.0.13、8.5.35 和 7.0.92 开始有针对此问题的内置解决方案:
1) 使用 JniLifecycleListener 加载原生库。
2) 使用 org.apache.tomcat.jni.Library 中的 loadLibrary() 或 load() 而不是 System.
在
的回答中查看更多详细信息和示例
我有一个在 Tomcat7 中部署的两个 Web 应用程序之间共享的 JNI 库 (.so)。我在第一个正在部署的 Web 应用程序中仅使用 System.loadLibrary 加载库一次,然后在第二个中我检查它是否已经加载以不再加载(我尝试在两者中加载它并且我得到 UnsatisfiedLinkError - 库被另一个类加载器加载)。我可以在第一个应用程序中对本机库进行任何调用,但在第二个应用程序中,我得到 UnsatisfiedLinkError 以及我尝试调用的方法名称。
我运行不知道自己能做什么。有任何想法吗?我在 SO 上尝试了大部分解决方案。 谢谢。
编辑 是的,我尝试在 tomcat lib 文件夹中添加库并从那里加载它。最初它在 bin 文件夹中,但出现了同样的问题。
您是否尝试过将共享 JNI 库放在 server.It 的 lib 目录中应该由所有部署的 Web 应用程序共享。
您需要从服务器类加载器而不是 webapp 类加载器中加载任何本机代码。我建议编写一个 Listener
将共享对象的二进制映像加载到 VM 中。这只会发生一次。请参阅 AprLifecycleListener
以了解如何正确执行此操作。它包括一个 JNI 组件,它可能完全代表您的情况。
共享对象必须驻留在 ${catalina.home}/lib
和 LD_LIBRARY_PATH
帽子中才能指向它。
是的,当您尝试加载已加载我的另一个 Web 应用程序的库时,会发生这种情况。 Tomcat,为每个 Web 应用程序使用单独的 class 加载器,它不允许您通过另一个 class 加载器
将同一个本地库多次加载到 JVM移动任何共享 jar 文件,如果有任何消耗您的 JNI sharedlib.so。将系统路径添加到 sharedlib ,
export LD_LIBRARY_PATH=/path/to/whereyourlinklibrary
像这样写一个简单的 class,这样您就可以在 tomcat 启动时加载您的共享库。只需编译此 class 并将其放入 tomcat lib 文件夹
package msm;
public class DLLBootstrapper {
static {
System.loadLibrary("sharedlib");
}
public static void main(String args[]) {
System.out.println("Loaded");
}
}
您现在可以从您的任何 Web 应用程序(可能在启动侦听器中)加载此 class
Class.forName("msm.DLLBootstrapper");
干得好!
Tomcat 从版本 9.0.13、8.5.35 和 7.0.92 开始有针对此问题的内置解决方案:
1) 使用 JniLifecycleListener 加载原生库。
2) 使用 org.apache.tomcat.jni.Library 中的 loadLibrary() 或 load() 而不是 System.
在