将OpenCV作为JBoss-作为全局模块 [英] OpenCV as JBoss-as global module
问题描述
我尝试将OpenCV安装为JBoss-as实例的全局模块.版本是:
I try to install OpenCV as global module of a JBoss-as instance. The versions are:
- JBoss-as:7.1.1最终版本
- OpenCV:2.4.5(带有Java支持)
我从全新安装的Ubuntu Server 12.04 64位开始,仅安装了JBoss-as和OpenCV.
I started from a fresh installation of Ubuntu Server 12.04 64 bits with only JBoss-as and OpenCV installed.
OpenCV Java包装器使用JNI调用.因此,需要做两件事:
The OpenCV java wrapper use JNI calls. Thus two things are required:
- opencv-245.jar
- libopencv_java245.so
并且在/usr/share/OpenCV/java/
中可用(关于安装)
And available in /usr/share/OpenCV/java/
(regarding to installation)
我还指出了一些看法:
- JBoss的安装正确(可以部署应用程序并且正在运行)
- 带有Java支持的OpenCV的编译和安装是正确的(使用OpenCV的Java类正在运行)
- 使用OpenCV并通过maven部署在JBoss-as works上的基本Web应用程序(
opencv-245.jar
在pom.xml
中被列为依赖项,因此打包到了war
中)
- The installation of JBoss is correct (applications can be deployed and are working)
- The compilation and installation of OpenCV with java support is correct (Java class using OpenCV are working)
- A basic web application using OpenCV and deployed, with maven, on JBoss-as works (the
opencv-245.jar
is listed as dependency inpom.xml
, and thus packaged into thewar
)
问题描述
一旦我将OpenCV定义为JBoss全局模块(在pom.xml中设置<scope>provided</scope>
),就会引发此异常:
Problem description
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)
似乎找到了OpenCV jar
库,因为从中引发了异常.此外,它也不会抱怨找不到类似的库(取自末尾的第一个链接):
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
因此,我想libopencv_java245.so
不是问题.准确的配置如下所述.
thus I guess the libopencv_java245.so
is not the problem. The precise configuration is described below.
我在modules/org/opencv/main/module.xml
中定义了org.opencv
模块:
<?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>
然后,我将相同的文件夹opencv-245.jar
和libopencv_java245.so
放在lib/linux-x86_64/
子文件夹中(如本地库)
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)
要将这个模块定义为全局模块,我在standalone/configuration/standalone.xml
中进行了修改:
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>
最后使用我在src/main/webapp/WEB-INF/jboss-deployment-structure.xml
中设置的全局模块:
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>
我还提醒我已经将<scope>provided</scope>
放入了行家pom.xml
.
I also reminds that I have put <scope>provided</scope>
in my maven pom.xml
.
另外,放:
System.loadLibrary("opencv_java245");
或不在代码中不会更改任何内容.
or not in the code doesn't change anything.
我还注意到,对于由一个war
和一个jar
组成的ear
应用程序,即使序言"中第3点中描述的过程也不起作用,并且给出与上述相同的例外.也许这些信息会有所帮助.
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?
- Path setting for DLL's in JBOSS 7.1.1
- JBoss 7 is trying to load modules libraries from JBoss bin
推荐答案
我终于解决了问题,并在此处写下了帮助其他人的答案.
I finally solve the problem and write here the answer to help other people.
问题不在libopencv_java245.so
的路径上,而是在JBoss Classloaders中.
The problem wasn't in the path of the libopencv_java245.so
, but in the JBoss Classloaders.
对于在序言第3点中描述的情况(有效),加载war
文件的ClassLoader与加载opencv-245.jar
(嵌入到war
中)相同,并且调用
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.
现在,它不能与ear
一起工作的原因是由于ear
具有其自己的ClassLoader,然后将每个子部署都作为另一个来进行的.第一个ClassLoader部署包含opencv-245.jar
依赖项的ear
,然后另一个ClassLoader部署包含在ear
中的war
.因为调用System.loadLibrary("opencv_java245")
在war
中,所以此命令的效果对war
的ClassLoader起作用,但是opencv-245.jar
被加载到ear
ClassLoader中.因此,当尝试调用本机库时,java找不到链接,因为它们位于不同的ClassLoader上.
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.
最后,这里的关注点是JBoss模块.当描述我最初的问题中配置的模块时,这是一个加载opencv-245.jar
的高级JBoss ClassLoader. ClassLoader还将自动知道在哪里搜索本机库:在$MODULE_PATH/lib/linux-x86_64/
中.但是问题是要加载库.对System.loadLibrary("opencv_java245")
的调用必须在对opencv-245.jar
收费的同一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");
}
因为它将对已加载您的类的ClassLoader起作用,而不对JBoss起作用.解决方案是修改opencv-245.jar
并在其中添加一个org.opencv.core.Loader
类,例如,该类只有一种方法:
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");
}
,放置在opencv-245.jar
中的System.loadLibrary
调用将与加载opencv-245.jar
的相同ClassLoader产生作用.然后正确链接了本机调用,因为jar
和so
这两个库都加载在同一ClassLoader中.
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.
这篇关于将OpenCV作为JBoss-作为全局模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!