今天用戶反饋應用閃退崩潰了。然後找呀找…
過程原來是這樣的:
還是說下項目背景
- 應用本身是個Android App,感覺這是費話呵,引用了一個JAVA項目。在應用啓動後會將App res/raw中的動態庫壓縮包複製到Sdcard進行解壓,然後使用System.load(libPath)加載。libPath是根據System.getProperty(“os.arch”);獲取當前處理器的架構動態匹配出來的(例:mnt/sdcard/mylib/armv7l/a.so)。
- 前期開發時只放了armv7l的動態庫,當一些有錢的客戶買了新的Android設備後,如果處理器是aarch64的架構,問題就來了,加載mnt/sdcard/mylib/aarch64/a.so時,這個路徑下是沒有so的。
- 與 此同時App項目的lib/目錄還是有其它so的。
Canney原創,轉載請註明:http://blog.csdn.net/canney_chen/article/details/50633982
爲解決上面的這個問題,那當然是再生成一個aarch64的動態庫。當這一些就緒後就出瞭如題UnsatisfiedLinkError a.so is 64-bit instead of 32-bit 的錯誤。
以下是對產生這個錯誤進行的相關研究
從錯誤信息可以看出:
- 從錯誤信息可以看出當前的a.so爲64 bit這個是沒有問題的。
- 但從 instead of 32-bit可以看出當前的環境並不是64 bit的而是32 bit。
當前設備是64 bit爲什麼運行的程序是32 bit環境??
於是找到了下面的這個資料:http://malideveloper.arm.com/downloads/01_Demystifying_64-bit_development_on_Android_Ramin_Zaghi.pdf
這份文檔第一部分寫了ARM 64-bit Architecture in Android™,其中的一個圖拉出來看看。
How Does It All Work?
- All Apps are forked from a background Virtual Machine (VM) process called Zygote
- Multilib devices run two Zygotes (a 32-bit one and a 64-bit one) in parallel!
- When an application is launched on a 64-bit system
- If it contains a supported 64-bit library, it runs as a 64-bit process against the loaded system
- If it contains a supported 32-bit library, it is launched as a 32-bit process
- Applications with no native code are launched using the default virtual machine (typically 64-bit)
上面這段話是原文對上圖的說明,能看懂的就略過我下面的解析。
- 所有的app運行都是由Zygote進程創建VM再運行的。
- 支持多種庫運行的設備,有兩個Zytgote(一個32-bit,一個64-bit)進程同時運行。
- 當App運行在64-bit 系統上時:
- 如果App包含64-bit庫,它將運行在一個64位進程中,即VM是由Zytgote 64創建的(圖中的2)。
- 如果App包含32-bit 庫,它將運行在一個32 bit進程中,即VM是由Zytgote創建的(圖中的3)
- 如果App不包含本地庫,它將默認運行在64 bit進程中。
對於圖中的1,4,5位置表明系統默認運行在64 bit進程中。
有了上面的基礎後,對錯誤就不難理解了:
1. App是否包含本地庫、32/64bit是從App/libs目錄下進行掃描的。
2. 我的應用在App/libs目錄下只有32 bit的so。根據上面的第二條可以判斷出我的應用Zytgote(32)創建的VM加載起來的。即32-bit進程在運行。
3. 動態從sdcard加載的a.so(64-bit)對應用啓動來說並不知道。
綜合上面的分析得出錯誤產生的原因。
解決辦法就是:
- 方法1:所有so都增加aarch64的so(動態加載及App/libs下的so)。
- 方法2:所有so都使用32-bit的(即把原來匹配aarch64目錄下的so,刪除換成32位的或將aarch64直接匹配到32位的arm7l目錄)。
總結一下
- aarch64是armv8架構下的64-bit執行狀態, 當然同版本下還有aarch32 32-bit執行狀態,具體可以查看[ARMv8 百度百科]
- 64-bit/32-bit 動態庫不能混用
- 64-bit處理器可以向下兼容32-bit指令集,即可以運行32-bit動態庫
- 當App中沒有使用到64-bit處理器特性且動態庫容量很大時可以考慮只使用32-bit動態庫,這樣可以減小安裝包的大小。
Canney原創,轉載請註明:http://blog.csdn.net/canney_chen/article/details/50633982