1. 程式人生 > >關於android,so庫那點事~~

關於android,so庫那點事~~

作者:Caspar
連結:https://zhuanlan.zhihu.com/p/21359984
來源:知乎
Android 應用開發中不可避免的會引入第三方的程式碼。如果是開源專案風險相對可控,如果引入商用的 SDK 那就要謹慎了,難免會有這樣或那樣的問題。比如我們今天要說的這一個。

對整合過第三方 SDK 的同學,上圖中的目錄結構應該不陌生。正常情況下我們只需要將不同版本的 .so 檔案分別放置。但如果我們要整合的這個第三方 SDK 偏偏沒有 arm-v7a 的版本呢?是刪除 armeabi-v7a 目錄只保留 armeabi ?還是說兩個目錄下 .so 檔案數不同也沒有關係?系統會載入哪個 .so 呢?

如果只對結論感興趣可以直接跳到最後

為了方便說明我們先引入 FAT Binary 的概念。我們知道不同的 CPU 支援的指令集也不一樣,那麼如果我們需要讓 App 儘可能不同的 CPU 上都可以正常執行該怎麼做呢?簡單,只需要將不同版本的 Binary 放在一個檔案裡,執行時按需取用就可以了。這就是 FAT Binary 的典型實現。Android 實現 FAT 的方式有些不同,就是上邊提到的將 .so 檔案放置在相應資料夾中。在 Android 系統中 ndk 預設會生成如下 7 種 .so。

在 apk 檔案中帶這麼多版本的 .so 是一種很不經濟的做法:

  • mips / mips64: 極少用於手機可以忽略
  • x86 / x86_64: x86 架構的手機都會包含由 Intel 提供的稱為
    Houdini
    的指令集動態轉碼工具,實現 對 arm .so 的相容,再考慮 x86 1% 以下的市場佔有率,x86 相關的兩個 .so 也是可以忽略的
  • armeabi: ARM v5 這是相當老舊的一個版本,缺少對浮點數計算的硬體支援,在需要大量計算時有效能瓶頸
  • armeabi-v7a: ARM v7 目前主流版本
  • arm64-v8a: 64位支援

這樣我們就可以明確 mips, mips64, x86, x86_64 這 4 個 .so 我們是不需要的。

我們回到開頭提到的問題:

假定我們現在的情況是這樣的(b.so 就是那個只有 armeabi 版本的第三方 .so):

如果這樣放置的話,在 ARM / ARM v7 兩種裝置上執行 apk 時會分別執行哪個 .so 呢?

答案是:不確定……

這麼坑爹的答案是怎麼來的呢?

由於 Android 上 FAT binrary 的設計如此陽春,在 apk 安裝時就需要根據 CPU 情況執行對應版本 .so 的拷貝。對上邊的情況最合理的一種做法應該是使用 armeabi-v7a/a.so 和 armeabi/b.so 這兩個檔案。Google 最初也是這麼想的,然後就引入了 Bug…

上圖是到 Android 4.4 還在使用的 .so 檔案拷貝邏輯,看起來沒有問題?

坑爹是 Android 在安裝 apk 檔案時沒有保證 zip entry 的掃描順序,所以同樣的檔案放置會帶來兩種不同的安裝結果:



看的有點頭暈?簡而言之,如果按我們上面的放置方式,安裝後系統可能只拷貝了 armeabi-v7a/a.so。如果執行到 b.so 的邏輯,程式顯然會 crash。

這邊還有個小插曲,這個 bug 的發現者在提交時其實已經給出了完善的解決方案,但在經歷了快有小一年的 code review 後 Android 官方表示:我們自己另起爐灶修好了=_=。


這個問題確實在 Android 5.0 已經 “修復” 了。“修復” 方式簡單粗暴,不再以檔案為粒度匹配 abi,直接拷貝整個資料夾=_=。所以如果按我們之前的放置方法,在 Android 5.0+ 如果執行到 b.so 也是一定會 crash 的。

上面提到,只保留 armeabi 資料夾從效能角度是不明智的。正確的做法是將 armeabi/b.so 複製一份到 armeabi-v7a/b.so. 這是由於 ARM v7 是前向相容 ARM v5 的。


撇開上面曲折離奇的故事,放置 .so 檔案的正確姿勢其實就兩句話:

  • 為了減小 apk 體積,只保留 armeabi 和 armeabi-v7a 兩個資料夾,並保證這兩個資料夾中 .so 數量一致
  • 對只提供 armeabi 版本的第三方 .so,原樣複製一份到 armeabi-v7a 資料夾

相關推薦

關於android,so~~

作者:Caspar 連結:https://zhuanlan.zhihu.com/p/21359984 來源:知乎 Android 應用開發中不可避免的會引入第三方的程式碼。如果是開源專案風險相對可控,如果引入商用的 SDK 那就要謹慎了,難免會有這樣或那樣的問題。比如我們今天要說的這一個。對整合過第三方 SD

初學Android Studio的

  剛接觸android三個月 發現android 就是以後的飯碗!得學明白 ! 可是空有一顆學習的心 還需要正確的方向呀!我就推薦幾個大佬  csdn 中的大佬太多了 這兒就說三個吧   guolin   鴻洋 啟艦 ======================

關於Android so的那些

Android 裝置的CPU型別(通常稱為”ABIs”) armeabiv-v7a: 第7代及以上的 ARM 處理器。2011年15月以後的生產的大部分Android裝置都使用它.arm64-v8a: 第8代、64位ARM處理器,很少裝置,三星 Galaxy S6是其

android除錯stetho的

在除錯安卓程式的過程中,受不了每次看日誌檢視網路的響應和匯出db的動作(甚至有時候都無法匯出db),這裡安利一個facebook出品的神器 stetho,不過這個有些限制,在使用的時候一定的通過usb與

Android 關於6.0,7.0許可權的

前言:最近把專案 targetSdkVersion 從22直接升級到27,因此就需要對新的動態許可權相關問題進行一籮筐的操作。寫這篇文章總結一下。 我在專案裡用的是EasyPermission工具類進行的動態許可權判斷。首先,在build.gradle中新增依賴: imp

Android GC

想寫一篇關於Android GC的想法來源於追查一個魅族手機圖片滑動卡頓問題,由於不斷的GC導致的丟幀卡頓的問題讓我們想了很多方案去解決,所以就打算詳細的看看記憶體分配和GC的原理,為什麼會不斷的GC, GC ALLOC和GC COCURRENT有什麼區別,能不能想辦法擴大堆記憶體減少GC的頻次等等。

Android開發之影象處理——濾鏡

code小生,一個專注 Android 領域的技術平臺公眾號回覆 Android 加入我的安卓技

Android 關於定位中的(GPS,GPGGA,NMEA-0183,RTCM)

首先關於定位一些解釋 通常在Android端地圖相關用的最多的都是第三方的Sdkj進行二次開發,如百度,高德,World Wind ,arcgis等,對於手機自帶的GPS晶片和國內的北斗晶片瞭解的相對較少,GPS在android中已經由android底層驅動封

android 螢幕寬高

  目錄 寬高的獲取方式 導航欄的高度獲取及導航欄監聽 寬高的獲取方式     1.  DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager

Android HTTP和HTTPS

先看看網路OSI(Open System Interconnect)模型: CA證書是什麼? CA(Certificate Authority)是負責管理和簽發證書的第三方權威機構,是所有行業和公眾都信任的、認可的。 CA證書,就是CA頒發

關於android真機訪問本地電腦伺服器以及訪問資料庫的

因為專案需要最近幾天在搗鼓android訪問伺服器以及伺服器連線本地資料庫相關的問題,沒什麼書籍可以參考,一路搞下來也是磕磕絆絆,好在經過一番努力最後還是成功地實現了功能,這裡就把我踩過的一些坑列舉出

設計模式--策略模式

簡化 cas enter ext font 想要 fonts 對象創建 客戶 概念: 策略模式定義了一系列的算法,分別封裝起來,讓它們之間能夠相互替換。此模式讓算法的變化,不會影響到使用算法的客戶。策略,實質上指的是算法。 樣例

談談字符串

沒有 register 用戶 今後 過程 破解 插件 運行 tro 在od破解軟件過程中,大家對於字符串應該是再熟悉不過了,但是往往事情不盡如人意,總是搜索不到想要的字符串,這時往往有的人會被迫用別的方法,消息斷點,內存斷點,硬件斷點等等,今天咱們只談字符串,把我所掌握的查

浮點數的

bsp 用兩個 處理 有一個 奇葩 加減乘 而且 出了 判斷 浮點數是計算機中儲存實數的形式。我們時常需要用浮點數去處理帶小數點的運算。可你是否知道,浮點數還有這些操作: 正負無窮大 與整數不同,浮點數沒有溢出的概念。當浮點數的運算結果超過一定範圍時,它的值就會根據運算結

新手···男生

for take edit ger har ping minutes lazy sgu 1、alarm clock go off鬧鐘響了,sleep right through it睡過去了,time to get up該起床, 2、you name it你說的 3、sle

mongodb第二篇文章~關於集群認證的

所有 目的 create 介紹 副本 這就是我 port pwd root 集群認證簡介:上一篇咱們介紹了單實力的認證方式,正好我在搞lepus監控,副本集合需要用戶認證 一 驗證方式: 1 auth 方式啟動=》單點 2 keyFile 方式啟動=》集群 請註意 開

PostgreSql(文件讀取寫入、命令執行的辦法)

ict con ext ews none urn truct 語法 tip ? 2013/07/9 作者: admin PostgreSql那點事(文件讀取寫入、命令執行的辦法) 今天無意發現了個PostgreSQL環境,線上學習了下,一般的數據註射(讀寫數據庫)差異不

搭建Maven私服

文件的 repos 版本控制工具 oracl 手工 apach security 項目 源碼 摘要:本文主要介紹在CentOS7.1下使用nexus3.6.0搭建maven私服,以及maven私服的使用(將自己的Maven項目指定到私服地址、將第三方項目jar上傳到私服供

this的

this指向 st2 開始 light pre 全局對象 很多 var 同時 對於很多初學者,this總是搞得我們暈頭轉向。 現在,我就簡單的總結一下關於this的那點事。 this在函數定義時經常是不能確定的,只有在函數執行的時候才能最終確定this的歸屬。this總是指

net 自定義泛型

toolbar user 定義和使用 程序 參考 關鍵字 double png 不同 泛型概述 泛型是程序設計語言的一種特性。允許程序員在強類型程序設計語言中編寫代碼時定義一些可變部分,那些部分在使用前必須作出指明。各種程序設計語言和其編譯器、運行環境對泛型的支持均不一樣