将OpenCV作为JBoss-作为全局模块 [英] OpenCV as JBoss-as global module

查看:121
本文介绍了将OpenCV作为JBoss-作为全局模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试将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)

我还指出了一些看法:

  1. JBoss的安装正确(可以部署应用程序并且正在运行)
  2. 带有Java支持的OpenCV的编译和安装是正确的(使用OpenCV的Java类正在运行)
  3. 使用OpenCV并通过maven部署在JBoss-as works上的基本Web应用程序(opencv-245.jarpom.xml中被列为依赖项,因此打包到了war中)
  1. The installation of JBoss is correct (applications can be deployed and are working)
  2. The compilation and installation of OpenCV with java support is correct (Java class using OpenCV are working)
  3. A basic web application using OpenCV and deployed, with maven, on JBoss-as works (the opencv-245.jar is listed as dependency in pom.xml, and thus packaged into the war)

问题描述

一旦我将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.jarlibopencv_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中)相同,并且调用在我的代码中对同一个ClassLoader起作用,因为它已加载了包含此方法调用的Class.都对同一个ClassLoader起作用,并且一切正常.

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产生作用.然后正确链接了本机调用,因为jarso这两个库都加载在同一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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆