前言
DK提供給用戶了兩個方法用於載入文件,一個是System.load(String filename)方法,另外一個是System.loadLibrary(String libname)方法。在任何本地方法被調用之前必須先用這個兩個方法之一把相應的JNI庫文件裝載。
System.load(String filename)
System.load 參數必須爲庫文件的絕對路徑,可以是任意路徑。
//Windows
System.load("C:\\Users\\TestJNI.dll");
//Linux
System.load("/usr/lib/TestJNI.so");
System.loadLibrary(String libname)
System.loadLibrary 參數爲庫文件名,不包含庫文件的擴展名。
System.loadLibrary ("TestJNI");
loadLibrary方法,在Android中調用默認是去jniLibs文件夾中對應手機架構的文件中找。
ClassLoader的findLibrary()實際上會在兩個部分的folder中去尋找System.loadLibrary()要load的那個library。一個部分是,構造ClassLoader時,傳進來的那個library path,即是app folder;另外一個部分是system property。在android系統中,查找要load的library,實際上會在如下3個folder中進行:
- /vendor/lib
- /system/lib
- /data/app-lib/com.example-1(只是一個例子,app包名都不一樣)
因爲加載順序不對造成的not found
例子:文件A.dll和文件B.dll有依賴關係,A.dll靜態鏈接到B.dll。此時我直接通過方法加載A.dll,System.load(“D:/A.dll”),結果報not found錯誤,我B.dll也放在D盤,爲啥找不到呢?
分析:因爲Java虛擬機在載入A.dll的時候,發現它依賴於B.dll,那麼會先去java.library.path下載B.dll,而B.dll並不位於java.library.path下。
解決:
- 先System.load(“D:/B.dll”)再System.load(“D:/A.dll”)
- 把A.dll和B.dll都放在java.library.path下,然後調用System.loadLibrary(“A”)
關於如何加到ava.library.path
先看看Windows下默認的路徑都有哪些:
默認情況下,Windows平臺下包含下面的路徑:
1)和jre相關的目錄
2)程序當前目錄
3)Windows目錄
4)系統目錄(system32)
5)系統環境變量path指定的目錄
所以最簡單的方式就是:我的電腦→屬性→環境變量→系統環境變量找到path,添加你自己的路徑。不過一般沒人這麼幹。只要按順序加載就行。
//可以打印一下路徑看看
System.out.println(System.getProperty("java.library.path"));