22

我有一个在 Tomcat 3.2.1 下运行的 webapp,它需要进行 JNI 调用才能访问遗留 C++ 代码中的数据和方法。servlet 在 webapp 启动时加载,作为其init方法的一部分,该 servlet 将特定于该 webapp 实例的数据集加载到 C++ 数据结构中。

此 servlet 的 Java 代码包含以下内容:

static
{
    try {
        System.loadLibrary("JCoreImpl");
        System.out.println("JCoreImpl loaded");
        m_bLibraryLoaded = true;
    } catch (UnsatisfiedLinkError e) {
        m_bLibraryLoaded = false;
        System.out.println("JCoreImpl NOT loaded " + e);
    }
}

如果只有一个 webapp(我们称之为“webapps/aaa”),一切都会很好。

如果我有第二个 webapp(“webapps/bbb”),除了 C++ 数据结构中使用的数据集之外,它与 webapps/aaa 相同,那么 webapps/aaa 启动得很好,但是当 webapps/bbb 启动时我得到一个错误指出:

JCoreImpl NOT loaded java.lang.UnsatisfiedLinkError: Native Library
E:\WebStation\binDebug\JCoreImpl.dll already loaded in another classloader

我需要为我的每个 web 应用程序拥有一个单独的本机库实例,因为每个实例都需要包含该特定 web 应用程序独有的数据。我搜索了邮件档案并阅读了 Craig McLanahan 解释类加载器层次结构的电子邮件。但是我找不到任何特定于为每个 webapp 加载本机库的唯一实例的东西。

4

4 回答 4

15

您不能两次加载相同的本机库。

将类放在 jar 文件下<tomcat>/lib/,它将在所有战争中共享。

于 2009-06-23T06:51:52.457 回答
9

请参阅Tomcat HowTo wiki ( http://wiki.apache.org/tomcat/HowTo )上的部分我在 Tomcat 下使用 JNI 时遇到类加载器问题

于 2009-07-08T23:34:27.187 回答
0

在加载它们之前,将 DLL 复制到临时目录中的临时文件。完成后删除文件。这样您就可以确保同一个 DLL 不会被加载两次。

于 2015-11-11T10:27:24.000 回答
0

我遇到了这个问题,我解决了:

问题:

问题是由于您的应用程序服务器的某些配置导致创建多个文件warear文件,因此它创建多个部署文件。这些部署的文件尝试同时访问加载在静态块中的本机库。

解决方案:

  1. 停止你的应用服务器并关闭 IDEA
  2. 从任务管理器完成所有java进程
  3. 转到您的应用服务器的此地址:jboss-eap-6.4.0\standalone\configuration并打开standalone.xml文件
  4. standalone.xml,删除所有deployments标签(不用担心,当您重新运行应用程序服务器时,它会插入此标签
  5. 转到您的应用服务器的这个地址: jboss-eap-6.4.0\standalone\deployments并删除所有已部署的文件和war文件。(你可以备份你的战争文件)
  6. 打开 IntelliJ Idea 并转到:编辑配置 JBOSS -> 部署选项卡
  7. 删除当前部署并添加一个应该是的新部署 exploded
于 2016-08-24T10:28:19.630 回答