5

问题介绍

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

  • JBoss-as:7.1.1 最终版
  • 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-as 上的基本 Web 应用程序(在opencv-245.jar中列为依赖项pom.xml,因此打包到 中war

问题描述

一旦我将 OpenCV 定义为 JBoss 全局模块(<scope>provided</scope>在 pom.xml 中设置),就会引发此异常:

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)

似乎jar找到了 OpenCV 库,因为它引发了异常。它也不会抱怨找不到某些库,例如(取自最后的第一个链接):

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>了我的 maven pom.xml

另外,放:

System.loadLibrary("opencv_java245");

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

额外的观察

我还注意到,对于ear由 onewar和 one组成的应用程序jar,即使“序言”中第 3 点中描述的程序也不起作用,并给出与上述相同的异常。也许这些信息可以提供帮助。

有人有一些指示或解决方案吗?

相关问题

4

3 回答 3

6

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

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

对于序言第 3 点中描述的情况(有效),加载文件的 ClassLoader 与加载相同war(嵌入opencv-245.jar到包含此方法调用的类。所有都对同一个 ClassLoader 产生影响,并且一切正常。warSystem.loadLibrary("opencv_java245")

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

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

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

因为它会对加载你的类的 ClassLoader 产生影响,而不是对 JBoss 产生影响。解决方案是修改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. 然后本地调用被正确链接,因为库jarso都加载在同一个 ClassLoader 中。

于 2013-04-26T08:53:26.273 回答
1

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

System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

您可以使用:

OpenCV.loadLocally();

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

于 2019-06-08T16:05:32.343 回答
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>
于 2013-04-23T15:36:19.213 回答