2010-07-26 164 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

相關問題