Android架构 armeabi、armeabi-v7a、arm64-v8a、x86详解
最近在用flutter打包的時(shí)候,遇到了包打不出來(lái)的情況,后面查了半天原因,發(fā)現(xiàn)是沒(méi)有配置arm導(dǎo)致的,配了之后就打出來(lái)了,乘著這個(gè)契機(jī),重頭來(lái)學(xué)習(xí)了一下abi
開(kāi)始之前
開(kāi)始之前先需要知道lib、libs等知識(shí)
一. lib和libs
放在lib中的是被reference的,放在libs中的是被include的。
放在libs中的文件會(huì)自動(dòng)被編輯器所include。所以不要把API放到libs里去。
lib的內(nèi)容是不會(huì)被打包到APK中,libs中的內(nèi)容是會(huì)被打包進(jìn)APK中
二. .so庫(kù)
NDK編譯出來(lái)的動(dòng)態(tài)鏈接庫(kù)。
一些重要的加密算法或者核心協(xié)議一般都用c寫(xiě)然后給java調(diào)用。這樣可以避免反編譯后查看到應(yīng)用的源碼。
三. .so庫(kù)該如何存放
放置 .so 文件的正確姿勢(shì)其實(shí)就兩句話(huà):
? 為了減小 apk 體積,只保留 armeabi 和 armeabi-v7a 兩個(gè)文件夾,并保證這兩個(gè)文件夾中 .so 數(shù)量一致
? 對(duì)只提供 armeabi 版本的第三方 .so,原樣復(fù)制一份到 armeabi-v7a 文件夾
存放so的規(guī)則:
你應(yīng)該盡可能的提供專(zhuān)為每個(gè)ABI優(yōu)化過(guò)的.so文件,但要么全部支持,要么都不支持:你不應(yīng)該混合著使用。你應(yīng)該為每個(gè)ABI目錄提供對(duì)應(yīng)的.so文件。
關(guān)于存放的問(wèn)題,可以詳細(xì)看看這篇
四. libs下armeabi等的作用是什么
存放.so庫(kù),主要針對(duì)不同的設(shè)備兼容,也可以說(shuō)是專(zhuān)門(mén)針對(duì)不同Android手機(jī)下CPU架構(gòu)的兼容。
下面就來(lái)扯一下安卓cpu
Android 設(shè)備的CPU類(lèi)型(通常稱(chēng)為”ABIs”)
架構(gòu)介紹
早期的Android系統(tǒng)幾乎只支持ARMv5的CPU架構(gòu),后面發(fā)展到支持七種不同的CPU架構(gòu):ARMv5,ARMv7 (從2010年起),x86 (從2011年起),MIPS (從2012年起),ARMv8,MIPS64和x86_64 (從2014年起),每一種都關(guān)聯(lián)著一個(gè)相應(yīng)的ABI。
應(yīng)用程序二進(jìn)制接口(Application Binary Interface)定義了二進(jìn)制文件(尤其是.so文件)如何運(yùn)行在相應(yīng)的系統(tǒng)平臺(tái)上,從使用的指令集,內(nèi)存對(duì)齊到可用的系統(tǒng)函數(shù)庫(kù)。在Android 系統(tǒng)上,每一個(gè)CPU架構(gòu)對(duì)應(yīng)一個(gè)ABI:armeabi,armeabi-v7a,x86,mips,arm64- v8a,mips64,x86_64。
但是最新的谷歌官方文檔已經(jīng)把mips和armv5移除了,如圖所示:
各版本分析如下:
? mips / mips64: 極少用于手機(jī)可以忽略(谷歌最新的文檔已經(jīng)不支持了)
? x86 / x86_64: x86 架構(gòu)的手機(jī)都會(huì)包含由 Intel 提供的稱(chēng)為 Houdini 的指令集動(dòng)態(tài)轉(zhuǎn)碼工具,實(shí)現(xiàn) 對(duì) arm .so 的兼容,再考慮 x86 1% 以下的市場(chǎng)占有率,x86 相關(guān)的兩個(gè) .so 也是可以忽略的
? armeabi: ARM v5 這是相當(dāng)老舊的一個(gè)版本,缺少對(duì)浮點(diǎn)數(shù)計(jì)算的硬件支持,在需要大量計(jì)算時(shí)有性能瓶頸
? armeabi-v7a: ARM v7
? arm64-v8a: 64位支持,目前主流的版本,雖然網(wǎng)上很多博客都說(shuō)v7是主流版本,但是我親自試驗(yàn)了很多手機(jī),都是arm64-v8a的架構(gòu),測(cè)試機(jī)型包括小米5-小米9,華為P30,華為mate10,魅藍(lán)2等均是v8架構(gòu)
查詢(xún)手機(jī)cpu命令行:
無(wú)圖無(wú)真相:
只有一款不知名的oppo手機(jī),android系統(tǒng)4.3,用的是v7的架構(gòu)
ABI是如何工作的
2020.06更新, 看到一篇很好的文章搬過(guò)來(lái)了,感謝原作者(https://juejin.im/post/5eae6f86e51d454ddb0b3dc6)
官方文檔解釋如下:
Android 系統(tǒng)在運(yùn)行時(shí)知道它支持哪些 ABI,因?yàn)榘姹咎囟ǖ南到y(tǒng)屬性會(huì)指示:
- 設(shè)備的主要 ABI,與系統(tǒng)映像本身使用的機(jī)器代碼對(duì)應(yīng)。
- (可選)與系統(tǒng)映像也支持的其他 ABI 對(duì)應(yīng)的輔助 ABI。
此機(jī)制確保系統(tǒng)在安裝時(shí)從軟件包提取最佳機(jī)器代碼。
為實(shí)現(xiàn)最佳性能,應(yīng)直接針對(duì)主要 ABI 進(jìn)行編譯。例如,基于 ARMv5TE 的典型設(shè)備只會(huì)定義主 ABI:armeabi。相反,基于 ARMv7 的典型設(shè)備將主 ABI 定義為 armeabi-v7a,并將輔助 ABI 定義為 armeabi,因?yàn)樗梢赃\(yùn)行為每個(gè) ABI 生成的應(yīng)用原生二進(jìn)制文件。
64 位設(shè)備也支持其 32 位變體。以 arm64-v8a 設(shè)備為例,該設(shè)備也可以運(yùn)行 armeabi 和 armeabi-v7a 代碼。但請(qǐng)注意,如果應(yīng)用以 arm64-v8a 為目標(biāo),而非依賴(lài)于運(yùn)行 armeabi-v7a 版應(yīng)用的設(shè)備,則應(yīng)用在 64 位設(shè)備上的性能要好得多。
許多基于 x86 的設(shè)備也可運(yùn)行 armeabi-v7a 和 armeabi NDK 二進(jìn)制文件。對(duì)于這些設(shè)備,主 ABI 將是 x86,輔助 ABI 是 armeabi-v7a。
總的來(lái)說(shuō),就是一個(gè)Android設(shè)備可以支持多種ABI,設(shè)備主ABI和輔助ABI,以arm64-v8a為主ABI的設(shè)備,輔助ABI為armeabi-v7a和armeabi,以armeabi-v7a為主ABI的設(shè)備,輔助ABI為armeabi。
另外,x86 架構(gòu)的手機(jī)都會(huì)包含由 Intel 提供的稱(chēng)為 Houdini 的指令集動(dòng)態(tài)轉(zhuǎn)碼工具,實(shí)現(xiàn)對(duì) arm .so 的兼容,也就是說(shuō)有適配armeabi平臺(tái)的APP是可以跑在x86手機(jī)上的。
ABI具體適配流程
對(duì)于一個(gè)cpu是arm64-v8a架構(gòu)的手機(jī),它運(yùn)行app時(shí),進(jìn)入jnilibs去讀取庫(kù)文件時(shí),先看有沒(méi)有arm64-v8a文件夾,如果沒(méi)有該文件夾,去找armeabi-v7a文件夾,如果沒(méi)有,再去找armeabi文件夾,如果連這個(gè)文件夾也沒(méi)有,就拋出異常;
如果有arm64-v8a文件夾,那么就去找特定名稱(chēng)的.so文件,注意:如果沒(méi)有找到想要的.so文件,不會(huì)再往下(armeabi-v7a文件夾)找了,而是直接拋出異常。
我們項(xiàng)目中該如何適配呢
Q1: 只適配了armeabi-v7a,那如果APP裝在其他架構(gòu)的手機(jī)上,如arm64-v8a上,會(huì)蹦嗎?
A: 不會(huì),但是反過(guò)來(lái)會(huì)。
因?yàn)閍rmeabi-v7a和arm64-v8a會(huì)向下兼容:
- 只適配armeabi的APP可以跑在armeabi,x86,x86_64,armeabi-v7a,arm64-v8上
- 只適配armeabi-v7a可以運(yùn)行在armeabi-v7a和arm64-v8a
- 只適配arm64-v8a 可以運(yùn)行在arm64-v8a上
那我們?cè)撊绾芜m配呢?給出如下幾個(gè)方案:
方案一:只適配armeabi
優(yōu)點(diǎn):基本上適配了全部CPU架構(gòu)(除了淘汰的mips和mips_64)
缺點(diǎn):性能低,相當(dāng)于在絕大多數(shù)手機(jī)上都是需要輔助ABI或動(dòng)態(tài)轉(zhuǎn)碼來(lái)兼容
方案二:只適配 armeabi-v7a
同理方案一,只是又篩掉了一部分老舊設(shè)備,在性能和兼容二者中比較平衡
方案三: 只適配 arm64-v8
優(yōu)點(diǎn): 性能最佳
缺點(diǎn): 只能運(yùn)行在arm64-v8上,要放棄部分老舊設(shè)備用戶(hù)
這三種方案都是可以的,現(xiàn)在的大廠(chǎng)APP適配中,這三種都有,大部分是前2種方案。具體選哪一種就看自己的考量了,以性能換兼容就arm64-v8,以兼容換性能armeabi,二者稍微平衡一點(diǎn)的就armeabi-v7a。
對(duì)于64位手機(jī)跟64位處理器
ARM64位處理器和電腦的64位處理器是兩個(gè)截然不容的概念,他并不是64位就能原生向下兼容32位程序,而是通過(guò)64位處理器中集成的32位架構(gòu)來(lái)運(yùn)行32位程序。說(shuō)得通俗點(diǎn),它不是以64位形態(tài)來(lái)運(yùn)行32位程序,卻是以32位的形態(tài)運(yùn)行32位程序的。
由于目前新出的64位處理器包含兩個(gè)架構(gòu),而且制程技術(shù)沒(méi)有提升(28nm),同時(shí)在手機(jī)與平板上,芯片面積有著嚴(yán)格的限定,不能過(guò)分增加,這導(dǎo)致64位ARM處理器平均分配到每個(gè)架構(gòu)的晶體管數(shù)量銳減,也就是說(shuō)從64位處理器中的32位架構(gòu)方面,對(duì)于同規(guī)格的32位處理器而言,不但沒(méi)有提高,性能反而是一定規(guī)模下降的。但處理器廠(chǎng)家又必須給消費(fèi)者一個(gè)交代,以更好的推廣64位,所以廠(chǎng)家就必須在其他方面提升性能,以彌補(bǔ)CPU的晶體管數(shù)量減少帶來(lái)的損失。比如:更換性能更強(qiáng)的GPU、提升內(nèi)存帶寬、多核心虛擬單顆核心提升單核性能、聯(lián)合跑分軟件商修改跑分權(quán)重(提升GPU分?jǐn)?shù),降低CPU分?jǐn)?shù)的權(quán)重)等等。這樣,揚(yáng)長(zhǎng)避短,最終到達(dá)消費(fèi)者手里,用跑分軟件一跑,確實(shí)有提升,用戶(hù)開(kāi)心,廠(chǎng)家腰包也鼓了。
綜上所述,ARM64位處理器從嚴(yán)格意義來(lái)說(shuō),叫它ARM32+64更加貼切,他相對(duì)于ARM32位處理器,有倒退的地方,也有進(jìn)步的余地,但正因?yàn)榈雇思て鹆薃RM進(jìn)取的決心,讓它大刀闊斧的向前變革,不得不說(shuō)也算一種進(jìn)步。但ARM64在的手機(jī)上真的有用嗎?我只能說(shuō),目前確實(shí)沒(méi)啥用,但今后或許有。(其他地方搜羅的) 綜上所述,ARM64位處理器從嚴(yán)格意義來(lái)說(shuō),叫它ARM32+64更加貼切,他相對(duì)于ARM32位處理器,有倒退的地方,也有進(jìn)步的余地,但正因?yàn)榈雇思て鹆薃RM進(jìn)取的決心,讓它大刀闊斧的向前變革,不得不說(shuō)也算一種進(jìn)步。但ARM64在的手機(jī)上真的有用嗎?我只能說(shuō),目前確實(shí)沒(méi)啥用,但今后或許有。(其他地方搜羅的)
真正的64位手機(jī)并不止單純停留在處理器上,如果只因?yàn)樗奶幚砥魇?4位,就稱(chēng)其為64位手機(jī)的話(huà),我們可以毫不猶疑的說(shuō)這可能是虛假宣傳,好在聯(lián)想很聰明,在發(fā)布A678t和A805e宣傳的時(shí)候,只說(shuō)64位處理器手機(jī)。
“64位處理器手機(jī)”與“64位手機(jī)”是兩種天壤之別的概念:只要是處理器包含64架構(gòu)位的,就可以稱(chēng)“64位處理器手機(jī)”,這種手機(jī)也許還運(yùn)行不了64位程序,只是用來(lái)?yè)屨际袌?chǎng),和32位手機(jī)比起來(lái)優(yōu)勢(shì)并不明顯。
“64位手機(jī)”就不同了:它包含著64位處理器、64位標(biāo)準(zhǔn)系統(tǒng)、64位安卓虛擬機(jī)、以及64位程序,這才是真正意義上的64位手機(jī)!
谷歌官方曾說(shuō),安卓很早前就支持64位了,這話(huà)不假,從Android4.0到Android4.4,安卓系統(tǒng)都支持64位的硬件,但是這僅僅表示底層驅(qū)動(dòng)支持64位,能運(yùn)行在64位的硬件之上,僅此而已。然而,上層運(yùn)行軟件的,無(wú)論是Dalvik的虛擬機(jī),還是ART虛擬機(jī)都是32位的。也就是說(shuō),只要你的手機(jī)系統(tǒng)是Android4.0—4.4,即便你的處理器是64位,也只能在32位虛擬機(jī)下運(yùn)行32位程序,就算真的64位程序擺在你眼前,也無(wú)法安裝。。
但是谷歌官方2019年初就已經(jīng)發(fā)布強(qiáng)制需要64位架構(gòu):
早在今年(2019)一月份,Google 就發(fā)布通知,在今年 8 月 1 日開(kāi)始,上架的 App,除了提供 32 位的版本之外,還需要提供 64 位的版本。
因此,項(xiàng)目之前強(qiáng)制只使用armeabi一種架構(gòu)的方式已經(jīng)不行了。
那這里說(shuō)的 64 位版本支持,到底是什么?
如果你的應(yīng)用,完全是使用 Java 或者 Kotlin 編寫(xiě)代碼,不包含任何原生(Native)的支持,那么就表示這個(gè)應(yīng)用已經(jīng)支持 64 位。
但是應(yīng)用內(nèi)使用了任何原生(Native)的支持(so 庫(kù)),就需要針對(duì)這些 so 文件,針對(duì)不同的 CPU 架構(gòu)提供不同的版本的 so 支持。
需要注意的是,有些時(shí)候,在我們自身的代碼中,確實(shí)沒(méi)有用到原生的支持,但是在 App 中使用的一些第三方庫(kù)中卻包含了。
此時(shí)最穩(wěn)妥的方式,就是針對(duì)最終打包生成的 APK 文件進(jìn)行分析,來(lái)判斷是否需要提供 64 位架構(gòu)的支持。
打包配置
split分包
這個(gè)命令可以按照各種規(guī)則去分包,比如按照abi,屏幕密度(即ldpi,hdpi等)分包
include就是包括,exclude就是不包括。包括的配置每一個(gè)項(xiàng)都會(huì)生成一個(gè)apk包。
但是這樣配置,會(huì)生成兩個(gè)包,一個(gè)只包含x86的so庫(kù),一個(gè)只包含armabi的so庫(kù)。,顯然不符合需求
ndk{abiFilters:}過(guò)濾
這個(gè)指令可以配置只打包你配置的so庫(kù),沒(méi)有配置的就不打包,很靈活。
第三方aar文件,如果這個(gè)sdk對(duì)abi的支持比較全,可能會(huì)包含armeabi、armeabi-v7a、x86、arm64-v8a、x86_64五種abi,而你應(yīng)用的其它so只支持armeabi、armeabi-v7a、x86三種,直接引用sdk的aar,會(huì)自動(dòng)編譯出支持5種abi的包。但是應(yīng)用的其它so缺少對(duì)其它兩種abi的支持,那么如果應(yīng)用運(yùn)行于arm64-v8a、x86_64為首選abi的設(shè)備上時(shí),就會(huì)crash了,所以我們需要在我們的app中配置 abiFilter 配置,來(lái)避免一些未知的錯(cuò)誤
//過(guò)濾x86的so庫(kù) ndk {abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a' }這樣配置會(huì)將armeabi,armeabi-v71,arm64-v8a這3個(gè)包下的so庫(kù)都打包到一個(gè)apk,而不像splits會(huì)每一個(gè)包打一個(gè)apk.
參考:
對(duì)于android cpu架構(gòu) ARM 和x86的區(qū)別 按照cpu架構(gòu)分別打包Apk
Android 中arm64-v8a、armeabi-v7a、armeabi、x86簡(jiǎn)介~
https://juejin.im/post/5eae6f86e51d454ddb0b3dc6
總結(jié)
以上是生活随笔為你收集整理的Android架构 armeabi、armeabi-v7a、arm64-v8a、x86详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 程序员职业生涯的11个阶段程序人生
- 下一篇: 使用软件测试路由器性能报告,路由器软件测