java如何修改java.library.path並且不重啟jvm也能生效


先說一下需求吧,

目前在用JCEF實現java程序桌面版包裝,源碼中需要加載編譯好的幾個dll文件,而這些文件的路徑必然是根據程序安裝的路徑而變化的,這就需要在程序運行的時候,去動態修改java.library.path來實現dll文件的加載

 

最開始的時候,我想到了System.setProperty();但是不管怎么試,都沒辦法動態加載進來,后來google了一下,發現這個方法需要重啟JVM才行,原因看下面這段代碼:

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

這段代碼在ClassLoader類,loadLibrary方法中,這段代碼的意思很好理解,sys_paths為null的時候會去加載一次變量,也就是說JVM啟動后就不可能再去加載,既然不能直接用System.setProperty();那就只能另尋他路,我開始在網上找資料,不難找到很多博客(原創或轉載)提供了一種方法,代碼如下:

 private static void addLibraryDir(String libraryPath) throws Exception {
	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);
}

我用這種方法,把我的路徑加進去了,但是在實際加載的時候,仍然找不到,這就有點尷尬了,我懷疑是不是自己的代碼出錯了,還是加路徑的位置不對,但是嘗試了N久,該方法始終無法跑通,也許是小弟資質略差,如有幸有大神看到此處,還望指點迷津

 


 

既然此路不通,咱也不能在一棵樹上吊死不是,另尋他路,英文蹩腳的我無奈實處必殺技,在google上開始搜索英文資料,google搜索 “java modify java.library.path at runtime” 沒想到第一條搜索就解決了我的問題!!!!!!

changing-java-library-path-at-runtime

該博客的第一個方法,還是最上面那兩行代碼,還是那個位置,該博客博主的方法就是設置sys_paths為null,既然每次只有在null的時候會初始化,那你何不設置路徑后,重新置為null,讓他下次執行的時候繼續初始化呢?年少的我還是有很多路要走啊,這么看似簡單的想法,居然一直沒有想到,慚愧...

借鑒該方法,最后代碼如下:

private static void addLibraryDir(String libraryPath) throws Exception {
	Field userPathsField = ClassLoader.class.getDeclaredField("usr_paths");
	userPathsField.setAccessible(true);
	String[] paths = (String[]) userPathsField.get(null);
	StringBuilder sb = new StringBuilder();
	for (int i = 0; i < paths.length; i++) {
		if (libraryPath.equals(paths[i])) {
			continue;
		}
		sb.append(paths[i]).append(';');
	}
	sb.append(libraryPath);
	System.setProperty("java.library.path", sb.toString());
	final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
	sysPathsField.setAccessible(true);
	sysPathsField.set(null, null);
}

好了,問題完美解決,心中一塊石頭落地,中午又可以多吃兩塊肉了,哈哈~~

 該文章最新發表於CSDN博客,后為推廣,在博客園發表一份,文章為原創兼翻譯,轉載請注明出處,謝謝!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM