2011-02-16 35 views
14

在一個Java項目中,我使用的是通過如何通過Java代碼影響System.loadLibrary()的搜索路徑?

System.loadLibrary("libName"); 

加載一些機庫的第三方庫,我想能夠從我的應用程序中的影響這種方法的搜索路徑,從而使用戶不需要在命令行上指定正確的java.library.path值(該值取決於當前的操作系統和體系結構)。例如,在Windows上我想將它設置爲 「LIB /本地/窗口」,在Linux上的32位爲 「LIB /本地/ linux32鏡像」 等

我試圖

System.setProperty("java.library.path", ...) 

但這被忽略,這顯然是因爲在我的代碼運行之前,JVM只讀取一次該屬性。

我也試圖與

System.load("fullPath/lib") 

此調用成功使用依賴於它的Java庫前加載本地libray,但仍然會有一個UnsatisfiedLinkError當本機庫與系統再次加載。調用LoadLibrary()。

我發現的唯一方法如下:

  • 添加接口抽象外部庫的整個API。
  • 在代碼的其餘部分只使用這些接口。
  • 添加實現接口並委託給庫的類。
  • 寫一個自己的ClassLoader,那
    • 覆蓋findLibary(),使本機庫是在正確的路徑
    • 覆蓋的loadClass(發現),並通過自身加載外部庫的所有類和包裝層,而不是試圖委託給它的父類的默認的ClassLoader會做
  • 確保接口加載與正常類加載器和包裝類和外部庫裝載有我自己的ClassLoader。

這可行,但我覺得它非常複雜,它很費力,因爲我需要添加所有這些接口。有一種更簡單的方法嗎?

+0

做過或沒做過System.load(「fullPath/lib/native/windows/libName.dll」)?爲什麼你用`System.loadLibrary(..)`重新加載它? – dacwe 2011-02-16 07:44:20

+0

@dacwe是的,它確實有效。但是第三方庫嘗試使用System.loadLibrary(..)重新加載它,並且失敗。 – 2011-02-16 08:00:52

回答

1
  1. 您無法更改正在運行的JVM的庫路徑。
  2. 您無法多次加載本機庫...你無法卸載本機庫,這樣就可以再次將其裝入:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4171986

基礎上您的評論以上(特別是對第三方庫的行爲),我會說,你最好的選擇是在啓動JVM時獲取庫路徑。

0

有沒有更簡單的方法?

是的,提供批處理/腳本文件來啓動應用程序。然後,您可以在批處理/ shell文件中設置正確的路徑,甚至可以從環境變量中讀取值。然後嘗試從應用程序內部執行它更容易。

+2

是的,這是我們目前所做的。但是,這不適用於從IDE中啓動它,或將其用作Eclipse插件的用戶。 – 2011-02-16 08:02:30

1

我試着以下,其中庫在我的應用程序的classpath的根目錄加載本地低吼庫我的Mac上的Java應用程序:

System.load(GrowlUtils.class.getResource("/libgrowl.jnilib").getFile().toString()); 
+1

我能夠在我自己的代碼中加載庫,這是沒有問題的。問題是第三方代碼用`System.loadLibrary(「libName」);`加載庫,所以我需要一種方法來影響此方法的行爲,而不是加載庫的另一種方式。 – 2011-08-28 08:52:07

4

我需要改變的dll路徑我的單元測試。我嘗試了下面的技巧和它的工作:

System.setProperty("java.library.path", "/path/to/libs"); 
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths"); 
fieldSysPath.setAccessible(true); 
fieldSysPath.set(null, null); 

有關說明,請參閱original link