JNI裝載庫文件load和loadLibrary淺析

前言

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中進行:

  1. /vendor/lib
  2. /system/lib
  3. /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下。

解決:

  1. 先System.load(“D:/B.dll”)再System.load(“D:/A.dll”)
  2. 把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"));

參考鏈接:Android中Java中System.loadLibrary() 的執行過程

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