我正在尝试从Web应用程序调用JNI本机函数。在过去,这一直有效,但是我不得不更改工作方式,因为我们要添加一个额外的Web应用程序,该应用程序也使用相同的动态库。遗憾的是,该库无法在两个单独的类加载器中加载。
无论如何,为了实现此目的,我已经在Tomcat 8的通用类加载器中加载了该库。我正在使用this answer作为模板。我相信我有充分的证据证明这确实有效。我正在使用this snippet检查我的库是否已加载并查看在哪个类加载器中。
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
目录中,但我宁愿避免这种情况。