問:能簡單說說通過 JNI 使用 Native 庫時 load 與 loadLibrary 方法的區別嗎?
答:可以說只要接觸過 JNI 開發的就一定要掌握這個知識點。JDK 提供給了我們兩個方法用於載入庫文件,一個是 System.load(String filename) 方法,另一個是 System.loadLibrary(String libname) 方法,他們的區別主要如下分析。
-
加載的路徑不同;System.load(String filename) 是從作爲動態庫的本地文件系統中以指定的文件名加載代碼文件,文件名參數必須是完整的路徑名且帶文件後綴;而 System.loadLibrary(String libname) 是加載由 libname 參數指定的系統庫(系統庫指的是 java.library.path,可以通過 System.getProperty(String key) 方法查看 java.library.path 指向的目錄內容),將庫名映射到實際系統庫的方法取決於系統實現,譬如在 Android 平臺系統會自動去系統目錄、應用 lib 目錄下去找 libname 參數拼接了 lib 前綴的庫文件。
-
是否自動加載庫的依賴庫;譬如 libA.so 和 libB.so 有依賴關係,如果選擇 System.load("/sdcard/path/libA.so"),即使 libB.so 也放在 /sdcard/path/ 路徑下,load 方法還是會因爲找不到依賴的 libB.so 文件而失敗,因爲虛擬機在載入 libA.so 的時候發現它依賴於 libB.so,那麼會先去 java.library.path 下載入 libB.so,而 libB.so 並不位於 java.library.path 下,所以會報錯。解決的方案就是先 System.load("/sdcard/path/libB.so") 再 System.load("/sdcard/path/libA.so"),但是這種方式不太靠譜,因爲必須明確知道依賴關係;另一種解決方案就是使用 System.loadLibrary("A"),然後把 libA.so 和 libB.so 都放在 java.library.path 下即可。