在java程序中動態設置java.library.path

最近在做一個項目的過程中需要用到第三方的jar包和動態鏈接庫(dll),其中jar包可以直接引入,問題是在開發的時候dll可以放在System32下,

但是當項目完成後build的時候,這種方式就行不通了,所以必須考慮其他的方式來引用所需的dll文件。

我們知道,在VM參數處通過-Djava.library.path後將加載路徑指定到自己的lib目錄後,程序可以正常啓動

但這種方式顯然不夠靈活,受限於必須從main函數啓動,並且要手動的去指定虛擬機參數。

那麼我們現在就需要採取其他的方式,比如在項目的根目錄下建一個dll的文件夾,將要用到的dll文件放到此目錄下,然後

通過System類的setProperty函數來在代碼中動態的改變一下java.library.path的值。

如下:

System.setProperty("java.library.path","%ProjectPath%/dll");

問題是這種方式是行不通的,會報錯"no JIntellitype in java.library.path"。

查找原因:

代碼中設置不起作用,主要是因爲java.library.path只在jvm啓動時讀取一次,其他情況下的修改不會起作用的。可以參考下面的這個bug:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4280189

原因和ClassLoader的實現有關係。

查看jdk的源碼會發現如下實現:

 if (sys_paths == null) {
     usr_paths = initializePath("java.library.path");
     sys_paths = initializePath("sun.boot.library.path");
 }

系統緩存了java.library.path的值,並且一直都會是第一次加載時的值。

有人提到了下面的修改方法,

if(sys_paths == null) {
    sys_paths= initializePath("sun.boot.library.path");
}
    usr_paths= initializePath("java.library.path");

有問題,就會有人解決問題,google一下,會發現antony_miguel在一篇文章中,使用java的反射機制,完成了對於ClassLoader類中的usr_paths變量的動態修改,

public static void addLibraryDir(String libraryPath) throws IOException {
		try {
			Field field = ClassLoader.class.getDeclaredField("usr_paths");
			field.setAccessible(true);
			String[] paths = (String[]) field.get(null);
			for (int i = 0; i < paths.length; i++) {
				if (libraryPath.equals(paths[i])) {
					return;
				}
			}

			String[] tmp = new String[paths.length + 1];
			System.arraycopy(paths, 0, tmp, 0, paths.length);
			tmp[paths.length] = libraryPath;
			field.set(null, tmp);
		} catch (IllegalAccessException e) {
			throw new IOException(
					"Failedto get permissions to set library path");
		} catch (NoSuchFieldException e) {
			throw new IOException(
					"Failedto get field handle to set library path");
		}
	}


文章也同時指出了這種實現的侷限性,和jvm的實現強關聯,只要jvm實現不是用的變量usr_paths來保存java.library.path的值,這個方法就不能用了。
但是隻要知道源代碼,小小的改動就應該可以實現了。

 

通過調用上面的方法來將dll文件目錄加入java.library.path路徑下,然後使用System.loadLibrary("glpk_4_55")這樣的方式加載dll文件即可。

 

over~

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章