OpenCV as a global JBoss module

Presentation of the problem

I am trying to install OpenCV as a global JBoss instance module. Versions:

  • JBoss-as: 7.1.1 Final
  • OpenCV: 2.4.5 (compiled with Java support)

I started with a fresh install of 64-bit 64-bit Ubuntu Server with only JBoss and OpenCV installed.

Preamble

The OpenCV java shell uses JNI calls. Thus, two things are needed:

  • Opencv-245.jar
  • libopencv_java245.so

And available in /usr/share/OpenCV/java/ (regarding installation)

I also point out some observations:

  • JBoss installation is correct (applications can be deployed and work)
  • Compiling and installing OpenCV with java support is correct (Java class works using OpenCV)
  • The main web application using OpenCV and deployed with maven on JBoss-as works ( opencv-245.jar is listed as a dependency in pom.xml and is thus packaged in war )

Description of the problem

As soon as I define OpenCV as the global JBoss module (setting <scope>provided</scope> in pom.xml), this exception occurs:

 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 looks like the OpenCV jar library is found because an exception is thrown from it. Also, he does not complain that some library was not found (taken from the first link at the end):

 java.lang.UnsatisfiedLinkError: no xxxx in java.library.path 

so i think libopencv_java245.so not a problem. The exact configuration is described below.

Configuration

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 opencv-245.jar folder as well as libopencv_java245.so in the lib/linux-x86_64/ subfolder (as described in the Native Library )

To define this module as global, I changed it to 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 installed 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 remind you that I put <scope>provided</scope> in my maven pom.xml .

Also by placing:

 System.loadLibrary("opencv_java245"); 

or not, nothing changes in the code.

Additional observations

I also noticed that with the ear application, which consists of one war and one jar , even the procedure described in paragraph 3 of the "Preamble" does not work and gives the same exception as above. Perhaps this information may help.

Does anyone have some pointers or solutions?

Related Questions

+5
source share
4 answers

I will finally solve the problem and write the answer here to help other people.

The problem was not in the libopencv_java245.so path, but in the JBoss class loaders.

In the case described in preambular paragraph 3 (which worked), the ClassLoader loading the war file is the same as loading opencv-245.jar (which is built into war ), and the call to System.loadLibrary("opencv_java245") in my code affects to the same ClassLoader, because it loaded the class containing this method call. Everything affects the same ClassLoader, and everything works.

Now, the reason it does not work with ear is because ear has its own ClassLoader, and then each subkey as different. The first ClassLoader deploys an ear that contains opencv-245.jar dependecy, then the other ClassLoader deploys a war contained in ear . Since the call to System.loadLibrary("opencv_java245") is in war , the effect of this command affects ClassLoader war , but opencv-245.jar loaded into the ear ClassLoader. Thus, when trying to call its own library, java cannot find the link, because it is on another ClassLoader.

Finally, an interesting topic here for the JBoss module. When describing the module configured in my initial question, this is a high-level JBoss ClassLoader that loads opencv-245.jar . ClassLoader will also automatically know where to look for its own libraries: in $MODULE_PATH/lib/linux-x86_64/ . But the problem is loading the library. The call to System.loadLibrary("opencv_java245") must be done in the same ClassLoader that charged opencv-245.jar . Thus, it is not possible to load such a library into your code:

 static { System.loadLibrary("opencv_java245"); } 

because it will affect the ClassLoader that loads your class, not JBoss. The solution is to modify opencv-245.jar and add the org.opencv.core.Loader class to org.opencv.core.Loader , which has 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 a call to System.loadLibrary placed in opencv-245.jar will have the effect of the same ClassLoader that loads opencv-245.jar . Then the native call is correctly connected, because both the library and jar and so were loaded in the library.

+6
source

Add the libopencv_java245.so file to the same directory that you created for your OpenCV module. then add it as a resource so that it is added to the classpath and is available at runtime.

So now your module.xml will look like this:

 <?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.0" name="org.opencv"> <resources> <resource-root path="opencv-245.jar"/> <resource-root path="."/> </resources> <dependencies> <module name="javax.api"/> </dependencies> </module> 
0
source

Found this link that gives instructions on downloading Native Libraries

https://docs.jboss.org/author/display/MODULES/Native+Libraries

0
source

If you are using OpenCV (org.openpnp package) 3.4. 2+ instead:

 System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 

you can use:

 OpenCV.loadLocally(); 

I am using jboss wildfly and am having trouble performing multiple deployments. Native classes have already been loaded, but this solved the problem.

0
source

All Articles