2010-07-26 70 views
1

我有一个类调用本机函数从CMOS获取有关系统的信息。这个类有它加载含有本地函数库的静态初始化块,它看起来是这样的:如何避免两次调用System.load?

package lib.sysid; 

public class SysId 
{ 
    private static native int getSysIdNative(); 
    private static final String SYS_ID_PATH = "libsysid.so"; 

    static 
    { 
     System.load(SYS_ID_PATH); 
    } 

    public static int getSysIdFromCMOS() 
    { 
     int returnValue = getSysIdNative(); 
    } 
} 

根据我的测试中,该方法能正常工作,我第一次使用它,但如果我叫在稍后的时间再次方法,静态初始化块也运行,造成UnsatisfiedLinkError:

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

我怎样才能避免执行System.load()方法,如果它已经运行静态初始化块?

另外,有没有办法让我试图“卸载”库,如果它已经加载之前再次调用System.load()方法?

编辑:奇怪的是,如果我用try-catch块围绕System.load()调用,我仍然得到一个UnsatisfiedLinkError,但是这次它来自getSysIdNative()的实际调用。我看到的错误如下:

lib.sysid.SysId.getSysIdNative()I 

什么是“我”显示了?我试图附加一个调试器到这个代码来查看消息的填充位置,但到目前为止我还没有成功。

回答

2

只是一个猜测,但我认为单个JVM加载类(并执行其静态初始化)两次的唯一方法是使用不同的类加载器加载它。所以这里可能还有第二个类加载器,你不知道。这将适用于第二次执行不同(一组)类加载器的情况。

在“真实”操作系统下,java -verbose:class会给你加载器消息来验证。我不确定如何在嵌入式系统上验证这一点。您可以修改getSysId()以打印(?)或以某种方式转储对SysId.class.getClassLoader()的引用。

0

我认为@Carl是正确的。静态初始化程序可以在JVM中运行两次的唯一方法是该类是在多个类加载器中加载的。

lib.sysid.SysId.getSysIdNative()I What the heck is that "I" that shows up?

这很简单。 I基于由类文件格式定义的签名中类型的内部表示。特别是,I表示原始类型int;请参阅Class.getName()等。这与您的方法的返回类型相匹配。

(有点令人困惑的是,这些原始类型名称偶尔出现在应用程序空间中,但它们确实存在。另一种可以看到它们的情况是,当您从继承Object的方法实现的类调用toString()类)。

+0

这就是我看到的问题。我使用的系统中有一些逻辑“重新加载”了与系统相关的所有库文件,包括我的上述文件,但是它通过与第一次加载文件不同的类加载器来完成此操作。 – troyal 2010-07-27 18:15:14