I was addicted to the ClassLoader problem when introducing JNI's external library in the project I am currently participating in, so I would like to leave a solution as a memorandum.
Java8 wildfly-8.1.0.Final
The Java Native Interface (JNI) is a Java platform that combines programs written in Java with code (native code) written in other programming languages (such as C or C ++) that runs on the actual CPU. It is an interface specification for cooperation. (Quoted from Wikipedia: https://ja.wikipedia.org/wiki/Java_Native_Interface)
The main process is an external library implemented in C ++, and I was trying to incorporate it into Java using JNI.
When I created the build material, I had the following configuration.
service.ear
├ lib
│ └ jni.jar ← Place JNI jar here
├ META-INF
├ app1.jar
├ app2.jar
└ webapp.war
Deploying this material to WildFly and launching it will work fine the first time. The problem is that the following error occurs when Hot Deploy is performed after the second time.
java.lang.UnsatisfiedLinkError: Native Library xxxx.dll already loaded in another classloader
"It's already loaded in another classloader" ... why ... Restarting WildFly will resolve this issue, but Hot Deploy again will recur.
There seems to be a limitation that native libraries can only be loaded into one class loader. Both the first and second times are running on the same JVM, but this phenomenon occurs because different class loaders are used each time it is loaded, and as a result, the same JVM is loaded twice. is. (I interpreted it as, but please point out if it is wrong)
Removed the JNI jar file from the build material.
service.ear
├ lib ← Do not place JNI jar here
├ META-INF
├ app1.jar
├ app2.jar
└ webapp.war
Place the jar as a static module in WildFly.
wildfly-8.1.0.Final/modules/system/layers/base配下にフォルダを作成します。 (例)wildfly-8.1.0.Final/modules/system/layers/base/xxx/yyy/main
Place the jar file and module.xml in the created folder.
base/xxx/yyy/main
├ jni.jar
└ module.xml ← Create a new file
The contents of module.xml. Match the name of the madule tag with the directory structure created above.
<?xml version="1.0" encoding="UTF-8"?>
<module name="xxx.yyy" xmlns="urn:jboss:module:1.1">
<resources>
<resource-root path="jni.jar"/>
</resources>
</module>
Add a dependency to jboss-deployment-structure.xml.
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="xxx.yyy" export="true" />
</dependencies>
</deployment>
</jboss-deployment-structure>
With the above support, the ClassLoader error no longer appears even after HotDeploy. Since there were no other members around the middleware, I desperately investigated it, so I decided to leave it as a reminder. I'm not sure if this response is really correct, but I'm glad that the problem has been resolved for the time being.
WildFly class loading https://qiita.com/tama1/items/f1556886149722b87f78
Recommended Posts