先說一下需求吧,
目前在用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博客,后為推廣,在博客園發表一份,文章為原創兼翻譯,轉載請注明出處,謝謝!