OpenCV作为JBoss作为全局模块

时间:2013-04-23 15:27:58

标签: java opencv jboss java-native-interface

问题陈述

我尝试将OpenCV安装为JBoss-as实例的全局模块。版本是:

  • JBoss-as:7.1.1 Final
  • OpenCV:2.4.5(使用Java支持编译)

我从全新安装的Ubuntu Server 12.04 64位开始,只安装了JBoss-as和OpenCV。

序言

OpenCV java包装器使用JNI调用。因此需要做两件事:

  • 的OpenCV-245.jar
  • libopencv_java245.so

可在/usr/share/OpenCV/java/中找到(关于安装)

我也指出了一些观察:

  1. JBoss的安装是正确的(应用程序可以部署并正在运行)
  2. 使用java支持编译和安装OpenCV是正确的(使用OpenCV的Java类正在运行)
  3. 使用OpenCV并使用maven在JBoss上部署的基本Web应用程序(opencv-245.jarpom.xml中列为依赖项,因此打包到war)< / LI>

    问题描述

    只要我将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库,因为它引发了异常。此外,它并没有抱怨一些未找到的库(从最后的第一个链接获取):

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

    因此我猜libopencv_java245.so不是问题。精确配置如下所述。

    配置

    我在org.opencv中定义了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>
    

    然后我在opencv-245.jar子文件夹中放入了同一文件夹libopencv_java245.solib/linux-x86_64/(如Native Library中所述)

    将此模块定义为我在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中设置的全局模块:

    <jboss-deployment-structure>
        <deployment>
            <dependencies>
                <module name="org.opencv" />
            </dependencies>
        </deployment>
    </jboss-deployment-structure>
    

    我还提醒我已将<scope>provided</scope>放入我的专家pom.xml

    另外,放:

    System.loadLibrary("opencv_java245");
    

    或不在代码中不会改变任何东西。

    额外观察

    我还注意到,ear应用程序由一个war和一个jar组成,即使“前言”中第3点中描述的过程也不起作用并给出相同的例外情况如上。也许这些信息可以提供帮助。

    有人有指针或解决方案吗?

    相关问题

4 个答案:

答案 0 :(得分:6)

我终于解决了问题并在这里写下了帮助其他人的答案。

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

对于Preamble第3点(有效)中描述的情况,加载war文件的ClassLoader与加载opencv-245.jar(嵌入war)中的相同,并且我的代码中对System.loadLibrary("opencv_java245")的调用对同一个ClassLoader有影响,因为它已经加载了包含此方法调用的Class。所有这些都对同一个ClassLoader有影响,一切正常。

现在为什么它没有使用ear跟进的原因是ear有自己的ClassLoader,然后每个子部署都是另一个。第一个ClassLoader部署ear,其中包含opencv-245.jar依赖项,然后另一个ClassLoader部署war中包含的ear。由于调用System.loadLibrary("opencv_java245")位于war,因此此命令的效果会对war的ClassLoader产生影响,但opencv-245.jar会加载到ear中ClassLoader。因此,当尝试调用本机库时,java无法找到该链接,因为它们位于不同的ClassLoader上。

最后,这里的兴趣点是JBoss模块。在描述初始问题中配置的模块时,这是一个加载opencv-245.jar的高级JBoss ClassLoader。 ClassLoader还将自动知道在哪里搜索本机库:$MODULE_PATH/lib/linux-x86_64/。但问题是加载库。对System.loadLibrary("opencv_java245")的调用必须在收费为opencv-245.jar的同一个ClassLoader中完成。因此,无法在代码中加载这样的库:

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

因为它会影响已加载Class的ClassLoader,而不会影响JBoss的ClassLoader。解决方案是修改opencv-245.jar并添加一个org.opencv.core.Loader类,其中只有一个方法:

package org.opencv.core

class Loader
{
    public static void loadLibrary(String name)
    {
        System.loadLibrary(name);
    }
}

然后在你的班上你可以把:

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

System.loadLibrary中的opencv-245.jar调用将影响加载opencv-245.jar的同一个ClassLoader。然后正确链接本机调用,因为jarso这两个库都加载到同一个ClassLoader中。

答案 1 :(得分:1)

如果您使用的是OpenCV(org.openpnp软件包)3.4.2+,而不是:

System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

您可以使用:

OpenCV.loadLocally();

我正在使用jboss wildfly,并且在进行多个部署时遇到问题。本机类已经加载,但这解决了问题。

答案 2 :(得分:0)

将libopencv_java245.so文件添加到为OpenCV模块创建的同一目录中。然后将其添加为资源,以便将其添加到类路径中并在运行时可用。

所以你的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"/>
        <resource-root path="."/>
    </resources>
    <dependencies>
        <module name="javax.api"/>
    </dependencies>
</module>

答案 3 :(得分:0)

找到此链接,提供有关加载本机库的说明

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