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

查看:13
本文介绍了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/中可用(关于安装)

我也指出了一些观察:

  1. JBoss 安装正确(应用程序可以部署并运行)
  2. Java 支持的 OpenCV 编译安装正确(使用 OpenCV 的 Java 类工作正常)
  3. 使用 OpenCV 并使用 maven 部署在 JBoss-as 上的基本 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>),就会引发此异常:

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> 放在了我的 maven 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.

我还注意到一个 ear 应用程序,由一个 war 和一个 jar 组成,即使是在序言"不起作用并给出与上述相同的例外.也许这些信息会有所帮助.

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.

问题不在于 libopencv_java245.so 的路径,而在于 JBoss 类加载器.

The problem wasn't in the path of the libopencv_java245.so, but in the JBoss Classloaders.

对于序言点 3(有效)中描述的情况,加载 war 文件的 ClassLoader 与加载 opencv-245.jar(即嵌入到 war) 中,并且在我的代码中对 System.loadLibrary("opencv_java245") 的调用对同一个 ClassLoader 有影响,因为它已经加载了包含这个的类方法调用.所有这些都对同一个 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部署ear,其中包含opencv-245.jar依赖,然后另一个ClassLoader部署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 模块.在描述我最初的问题中配置的模块时,这是一个高级 JBoss ClassLoader,它加载 opencv-245.jar.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");
}

因为它会影响加载你的类的类加载器,而不是 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");
}

并且 System.loadLibrary 调用被放置在 opencv-245.jar 中将产生与加载 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天全站免登陆