I try to install OpenCV as global module of a JBoss-as instance. The versions are:
I started from a fresh installation of Ubuntu Server 12.04 64 bits with only JBoss-as and OpenCV installed.
The OpenCV java wrapper use JNI calls. Thus two things are required:
And available in /usr/share/OpenCV/java/
(regarding to installation)
I also point some observations:
opencv-245.jar
is listed as dependency in pom.xml
, and thus packaged into the war
)As soon as I define OpenCV as JBoss global module (setting <scope>provided</scope>
in pom.xml) this exception is raised:
java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_Mat()J
org.opencv.core.Mat.n_Mat(Native Method)
org.opencv.core.Mat.<init>(Mat.java:441)
WS.printMessage(WS.java:15)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:616)
org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:155)
org.jboss.resteasy.core.ResourceMethod.invokeOnTarget(ResourceMethod.java:257)
org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:222)
org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:211)
org.jboss.resteasy.core.SynchronousDispatcher.getResponse(SynchronousDispatcher.java:525)
org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:502)
org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:119)
org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:208)
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:55)
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:50)
javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
It appears that the OpenCV jar
library is found because the exception is raised from it. Also it does not complains about some library not found like (taken from first link at the end):
java.lang.UnsatisfiedLinkError: no xxxx in java.library.path
thus I guess the libopencv_java245.so
is not the problem. The precise configuration is described below.
I defined the org.opencv
module in modules/org/opencv/main/module.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="org.opencv">
<resources>
<resource-root path="opencv-245.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
</dependencies>
</module>
Then I put in the same folder opencv-245.jar
and also libopencv_java245.so
in lib/linux-x86_64/
subfolder (as explained in Native Library)
To define this module as global I modified in standalone/configuration/standalone.xml
:
<subsystem xmlns="urn:jboss:domain:ee:1.0">
<global-modules>
<module name="org.opencv" slot="main"/>
</global-modules>
</subsystem>
Finally to use the global module I set in src/main/webapp/WEB-INF/jboss-deployment-structure.xml
:
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.opencv" />
</dependencies>
</deployment>
</jboss-deployment-structure>
I also reminds that I have put <scope>provided</scope>
in my maven pom.xml
.
Also, putting:
System.loadLibrary("opencv_java245");
or not in the code doesn't change anything.
I also noticed that with an ear
application, composed of one war
and one jar
, even the procedure described in point 3 in "Preamble" does not work and give the same exception as above. Maybe this information can help.
Someone have some pointers or solutions?
I finally solve the problem and write here the answer to help other people.
The problem wasn't in the path of the libopencv_java245.so
, but in the JBoss Classloaders.
For the case decribed in Preamble point 3 (which worked), the ClassLoader that load the war
file is the same that load opencv-245.jar
(which is embedded into the war
), and the call to System.loadLibrary("opencv_java245")
in my code has effect on this same ClassLoader, because it has loaded the Class containing this method call. All has effect on the same ClassLoader and everything work.
Now the reason why it is not working with an ear
follow up from the fact that an ear
has its own ClassLoader, and then each subdeployment as another one. The first ClassLoader deploy the ear
, which contains the opencv-245.jar
dependecy, then another ClassLoader deploy the war
contained into the ear
. Because the call System.loadLibrary("opencv_java245")
is in the war
, the effect of this command has effect on the ClassLoader of the war
, but the opencv-245.jar
is loaded into the ear
ClassLoader. Thus when trying to call native library, java can't find the link because they are on different ClassLoader.
Finally the point of interest here is for a JBoss module. When describing a module as configured in my initial question, this is a high level JBoss ClassLoader which load the opencv-245.jar
. The ClassLoader will also automatically know where to search for native libraries: in $MODULE_PATH/lib/linux-x86_64/
. But the problem is to load the library. The call to System.loadLibrary("opencv_java245")
must be done in the same ClassLoader that have charged opencv-245.jar
. Thus it is not possible to load library like this in your code:
static {
System.loadLibrary("opencv_java245");
}
because it will has effect on the ClassLoader that have load your Class, not on the JBoss one. The solution is to modify the opencv-245.jar
and add into it a org.opencv.core.Loader
class for instance, which have only one method:
package org.opencv.core
class Loader
{
public static void loadLibrary(String name)
{
System.loadLibrary(name);
}
}
Then in your class you can put:
static {
Loader.loadLibrary("opencv_java245");
}
And the System.loadLibrary
call being placed in opencv-245.jar
will have effect one the same ClassLoader that load the opencv-245.jar
. Then native call are correctly linked because both library, the jar
and the so
, were loaded in the same ClassLoader.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With