1. 程式人生 > >android 5.0以上so檔案關於平臺支援問題的淺析

android 5.0以上so檔案關於平臺支援問題的淺析

背景
近期,因為一些原因,需要整理一個最簡單的外掛框架使用的demo,此過程中出現了一個非常詭異的問題,
在實際專案中一直執行正常的一些外掛,在demo裡面卻執行崩潰,得到的異常資訊如下:
06-01 15:44:59.462 26609 26609 E InstrumentationHacker: dlopen failed: "/data/data/qihoo.com.pluginloader/files/plugin/safebarcode/work/lib/armeabi/lib/armeabi/libmixed_sample.so" is 32-bit instead of 64-bit
06-01 15:44:59.462 26609 26609 E InstrumentationHacker: java.lang.UnsatisfiedLinkError: dlopen failed: "/data/data/qihoo.com.pluginloader/files/plugin/safebarcode/work/lib/armeabi/lib/armeabi/libmixed_sample.so" is 32-bit instead of 64-bit
06-01 15:44:59.462 26609 26609 E InstrumentationHacker: 	at java.lang.Runtime.loadLibrary(Runtime.java:372)
06-01 15:44:59.462 26609 26609 E InstrumentationHacker: 	at java.lang.System.loadLibrary(System.java:1076)
06-01 15:44:59.462 26609 26609 E InstrumentationHacker: 	at com.qihoo360.commoditybarcode.utils.JniInterface.init(JniInterface.java:15)

通過異常資訊,可以大致猜到,是由於so平臺相容問題引起的,但是丟擲異常的外掛裡面的so都是32位的存放在lib/armeabi下的,理論上來說,android 64位是可以相容32位so的,但是為什麼會出現這個問題呢?另外,在同樣的環境和裝置的情況下,實際專案中為什麼沒有這個問題呢?

android中不同平臺so的載入
平時應用開發中,我們的native程式碼,根據平臺/特性的不同需要編譯不同版本的so檔案,比如:"armeabi", "armeabi-v7a", "arm64-v8a","x86", "mips"等。而android在使用我們的so時,會根據自身cpu的特性,選擇最合適的一個版本,如果沒有,則選擇其次的相容版本,也就是說,如果同時存在arm64-v8a和armeabi,在64位系統下,系統優先選擇aarch64下的so檔案,如果aarch64下沒有so檔案,則依據特性選擇相容的32位版本(armeabi-v7a、armeabi等)。

另外,雖然64位系統能相容32位指令集,但是64位程序是無法載入32位so的,反過來也一樣,因此app要麼全使用64位的so,要麼全使用32位的so,不能混合使用。所以我們的應用中,針對某一平臺,要麼不支援,要麼所有so都支援,也就是說,在每一個lib下的平臺目錄中,要麼沒有so,要麼所有so都一致。


我們知道,android所有的程序都是從zygote程序fork()而來,而android 64位系統實際上有兩個zygote,分別命名為:zygote、zygote64,一個為32位程序,一個為64位程序,64位的應用通過zygote64位分裂,32位程序通過zygote分裂。

問題分析
綜上所述,應用在使用so時,會選擇最優方案,如果一個應用中沒有任何so檔案,在64位系統中以64位程序執行是最優的方案。
而在我們的外掛化方案中,宿主程式與外掛是分開的,如果宿主程式沒有任何so檔案,那麼64位系統會將其以64位執行。如果外掛只支援32位,則外掛在載入32位的so檔案時,必然出錯(不能混用)。
在我們使用System.load()載入一個外部的so時,也有可能存在類似的問題,原因與前述一樣。
由於我們在實際專案中,工程中存在armabi的so檔案,所以系統將應用以32位程序執行,所以外掛能正常執行。

解決方案1

在外掛中lib/arm64--v8a下加入一套64位so檔案即可,這樣它在64位下也能執行。

但是這樣會增大外掛體積,在某些情況下,我們不會想要帶入64位的so。

解決方案2

在宿主的armeabi目錄下隨便放入一個so檔案即可,為了不增大宿主的體積,可以放一個0位元組的空檔案,按照so命名規範命名。這樣64位系統執行應用時,會以相容32位模式執行。


參考文章:http://blog.csdn.net/canney_chen/article/details/50633982