Glassfish本地库加载(.dll,.so)

时间:2009-12-13 10:05:26

标签: java glassfish java-native-interface

我正在使用最近发布的Glassfish v3,在使用本地库时,glassfish会间歇性地抱怨

glassfish SEVERE: java.lang.UnsatisfiedLinkError: 
Native Library already loaded in another classloader

在之前的glassfish发行版(v2.2)中加载本机库的过程就是将.dll文件放在GLASSFISH_HOME \ lib中。现在我不知道v3中是否有这样一个神奇的文件夹,如果有的话。我还检查了管理界面,我认为有两个与我的问题有关的变量:Native Library Path Prefix和Native Library Path Suffix。我一直在网上搜索,找到他们做什么以及如何使用它们的充分描述,但显然没有人喜欢谈论它们。

2 个答案:

答案 0 :(得分:4)

java.lang.UnsatisfiedLinkError: Native Library already loaded in another classloader

本机lib只能在JVM中加载一次,并且每当您在重新部署时加载新版本的调用类(System.loadLibrary(String)调用所在的类)时,您将收到该错误消息。更多内容如下。

  

在之前的glassfish版本(v2.2)中加载本机库的过程就是将.dll文件放在GLASSFISH_HOME\lib中。

嗯,这实际上只是故事的第一部分。要加载本机库,您当然要将它放在库路径上以从Java代码加载它。为此,惯例是包括一个静态初始化器,如下所示:

class FooWrapper {
    static {
        System.loadLibrary("foo");
    }

    native void doFoo();
    }
}

假设您正在使用Web应用程序,最佳做法是不要将本机库或其JNI接口放在WEB-INF/libWEB-INF/classes下,以避免在重新加载应用程序时出现问题,如上所述。换句话说,调用System.loadLibrary(String)的类应该由不受重新加载Web应用程序本身影响的类加载器加载。

所以我的问题是:你把代码放在哪里了?

PS:另一种选择是在加载之前检查dll是否已经可用但我不会这样做。

答案 1 :(得分:3)

首先:给定的本地类只能加载到一个类加载器中。

第二件事:servlet容器中的每个Web应用程序都有自己的类加载器。

第三件事:您必须非常小心地编写本机代码以允许其类被垃圾收集。

结果:将本机代码加载到Web应用程序后,如果您尝试卸载并重新加载,可能会出现这些错误。

在某种程度上,我跳过了这个主题的非常简单的变体:只需加载两个不同的webapps和相同的本地类。

有些人更喜欢在系统类加载器中加载本机代码,以避免出现此问题。