首页 > 解决方案 > 无法从共享 Tomcat 类加载器中加载的库中调用本机函数

问题描述

我正在尝试从我的 Web 应用程序调用 JNI 本机函数。在过去,这一直有效,但我不得不改变我们的工作方式,因为我们正在添加一个额外的 Web 应用程序,它也使用相同的动态库。遗憾的是,该库无法在两个单独的类加载器中加载。

无论如何,为了实现这一点,我已经在 Tomcat 8 的通用类加载器中加载了该库。我使用这个答案作为模板。我相信我有强有力的证据表明这确实有效。我正在使用此代码段来检查我的库是否已加载并查看哪个类加载器。

Classloader: java.net.URLClassLoader@26b418
Loaded:
 C:\Program Files (x86)\Java\jdk1.8.0_202\jre\bin\zip.dll
 C:\Program Files (x86)\Java\jdk1.8.0_202\jre\bin\management.dll
 C:\Program Files (x86)\Java\jdk1.8.0_202\jre\bin\net.dll
 C:\Program Files (x86)\Java\jdk1.8.0_202\jre\bin\nio.dll
 C:\Program Files (x86)\Java\jdk1.8.0_202\jre\bin\sunec.dll
 C:\Program Files (x86)\Java\jdk1.8.0_202\jre\bin\sunmscapi.dll
 C:\Repositories\binaries\build\release\myAppJni.dll

Classloader: ParallelWebappClassLoader
  context: myApp-display
  delegate: false
  ----------> Parent Classloader:
  java.net.URLClassLoader@26b418
 C:\Program Files (x86)\Java\jdk1.8.0_202\jre\bin\zip.dll
 C:\Program Files (x86)\Java\jdk1.8.0_202\jre\bin\management.dll
 C:\Program Files (x86)\Java\jdk1.8.0_202\jre\bin\net.dll
 C:\Program Files (x86)\Java\jdk1.8.0_202\jre\bin\nio.dll
 C:\Program Files (x86)\Java\jdk1.8.0_202\jre\bin\sunec.dll
 C:\Program Files (x86)\Java\jdk1.8.0_202\jre\bin\sunmscapi.dll
 C:\Repositories\binaries\build\release\myAppJni.dll

这让我相信我的 JNI-DLL 实际上已加载到整个应用程序中,并且它应该可用于 Web 应用程序和我用作依赖项的其他库。

但是,当我尝试这个时。我得到一个类似这样的 UnsatisfiedLinkException:

java.lang.UnsatisfiedLinkError: org.my.application.printer_create_handle(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
at org.my.application.Printer.printer_create_handle(Native Method)

这或多或少类似于我根本不加载库时看到的行为。

当我退回到在静态块中加载库时,一切似乎都正常工作。但是当我添加第二个应用程序时,我会收到一条already loaded in another classloader消息。这对我来说很有意义,但它并没有让我更进一步。

我想我真的不明白这是如何正常工作的。任何人都可以对此有所了解吗?

我能看到解决这个问题的唯一方法是将我的库部署在 Tomcat8 的lib目录中,但我宁愿避免这种情况。

标签: javadllclassloadertomcat8

解决方案


推荐阅读