System.load(String filename)和System.loadLibrary(String libname)的區別

五月的倉頡發表於2015-09-21

前言

之前一篇文章在寫Native方法的時候,第一個步驟裡面有這麼一段程式碼

static
{
  System.load("D:" + File.separator + "Hello.dll");
}

其實JDK提供給使用者了兩個方法用於載入檔案,一個是System.load(String filename)方法,另外一個是System.loadLibrary(String libname)方法,本文主要寫一下這兩個方法之間的區別。

 

區別

1、載入的路徑不同

System.load(String filename)我們看JDK API的描述是“從作為動態庫的本地檔案系統中以指定的檔名載入程式碼檔案。檔名引數必須是完整的路徑名”,因此這個方法的引數必須是要載入的檔案的完整路徑,帶檔案字尾名。

System.loadLibrary(String libname)我們看JDK API的描述是“載入由libname引數指定的系統庫。將庫名對映到實際系統庫的方法取決於系統”,這裡關鍵問題就是系統庫三個字。什麼是系統庫,做個實驗,修改一下static塊中的程式碼,用loadLibrary方法來載入

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

執行一下,看一下結果

看到報錯了,在java.library.path中沒有找到Hello,OK,那這樣就很簡單了,我們知道了系統庫指的是java.library.path,用System.getProperty(String key)方法檢視一下java.library.path指向的內容

public static void main(String[] args)
{
	System.out.println(System.getProperty("java.library.path"));
}

列印的內容太多了,就不放上來了,反正放到任意的一個路徑下都可以,注意一下不要帶字尾名。至於java.library.path指的是什麼,網上很多,就不做複製黏貼的工作了。

2、這個是網上看別人寫的才知道的,假如A.dll和B.dll有依賴關係,比如A.dll靜態連結到B.dll,那麼如果選擇System.load("D:/A.dll"),即使B.dll也放在D:/路徑下,load方法還是會因為找不到依賴的.dll檔案而失敗。因為Java虛擬機器在載入A.dll的時候,發現它依賴於B.dll,那麼會先去java.library.path下載入B.dll,而B.dll並不位於java.library.path下。有兩個解決方案:

(1)先System.load("D:/B.dll")再System.load("D:/A.dll")

(2)把A.dll和B.dll都放在java.library.path下,然後呼叫System.loadLibrary("A")

不過兩個dll檔案存在依賴關係,A.dll依賴於B.dll,屬於別的領域的知識,我也不是很清楚,所以第二點也沒有親身試驗過。權當把這個知識點放在這兒,以後萬一遇到類似問題了,也有個解決問題的方向。

相關文章