日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

android odex版本调试_Android可执行文件之谜 - DEX与ODEX, OAT与ELF

發(fā)布時(shí)間:2023/12/19 Android 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android odex版本调试_Android可执行文件之谜 - DEX与ODEX, OAT与ELF 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

米娜桑,是時(shí)候揭開(kāi)DEX的面紗了!我們都知道m(xù)ultidex,都知道65535方法數(shù)超標(biāo),那DEX到底是個(gè)什么東西呢?或許又有些同學(xué)知道DEX會(huì)優(yōu)化為ODEX,那ODEX又是什么鬼,優(yōu)化了什么呢?為什么ClassLoader熱補(bǔ)丁方案插入構(gòu)造函數(shù)導(dǎo)致CLASS_ISPREVERIFIED為false后,會(huì)對(duì)性能造成影響,和ODEX又有什么關(guān)系呢?

我們又知道5.0以上Android虛擬機(jī)變成了Art,那DEX在art上變成了什么呢?為什么安裝特別耗時(shí)間?有時(shí)候我看著我的Nexus6安裝一個(gè)應(yīng)用在那進(jìn)度條讀啊讀的好像卡住了,有一種想砸了它的想法,所以當(dāng)我拿到Nexus 5測(cè)試機(jī)的時(shí)候,第一件事就是刷到4.4,不然每次安裝的效率實(shí)在不能忍(捂臉)。

DEX是什么

直接把a(bǔ)pk當(dāng)成zip打開(kāi)后,第一級(jí)目錄你就會(huì)看見(jiàn)有classes.dex,這就是我們要揭開(kāi)面紗的東西了。

Why DEX

為什么需要DEX,jar不行嗎?相應(yīng)地,為什么需要Dalvik虛擬機(jī),JVM不行嗎?

Dalvik虛擬機(jī)是專門為了Android移動(dòng)平臺(tái)設(shè)計(jì)的。目標(biāo)系統(tǒng)的RAM有限,數(shù)據(jù)存儲(chǔ)在緩慢的內(nèi)部閃存上,而且性能和上個(gè)世紀(jì)的周免系統(tǒng)相當(dāng)。它們運(yùn)行Linux,來(lái)提供虛擬內(nèi)存,進(jìn)程和線程,以及基于UID的安全機(jī)制。

這些特征和限制使我們聚焦在這些目標(biāo)上:類數(shù)據(jù),尤其是字節(jié)碼,必須被多個(gè)進(jìn)程共享,以最小化系統(tǒng)內(nèi)存使用。

啟動(dòng)一個(gè)新app的開(kāi)銷必須最小化,來(lái)保證設(shè)備的可響應(yīng)。

在獨(dú)立的文件存儲(chǔ)類數(shù)據(jù)可能導(dǎo)致很多冗余,尤其是字符串。為了保證磁盤空間,我們需要把這些因子提出來(lái)。

解析類數(shù)據(jù)的fields在類加載的時(shí)候增加了很多不必要的開(kāi)銷。把數(shù)據(jù)值直接當(dāng)成C類型(比如整數(shù)或字符串)使用會(huì)更好。

字節(jié)碼驗(yàn)證是必要的,卻也是緩慢的。所以我們想在app執(zhí)行外盡量驗(yàn)證更多,以便不要影響app本身體驗(yàn)。

字節(jié)碼優(yōu)化(加速指令,精簡(jiǎn)方法)對(duì)速度和電池生命很重要。

為了安全原因,進(jìn)程不能編輯共享代碼。

典型的虛擬機(jī)執(zhí)行從壓縮文件解壓獨(dú)立的類,然后把它們存到heap上。這就導(dǎo)致了每個(gè)類可能在每個(gè)進(jìn)程有獨(dú)立的拷貝,從而使得應(yīng)用啟動(dòng)變慢,因?yàn)榇a必須被解壓(或者至少需要從磁盤的很多小片段去讀取)。另一方面,在本地heap放置字節(jié)碼簡(jiǎn)化了首次使用時(shí)的指令重寫,從而可能導(dǎo)致一些不同的優(yōu)化。

這些目標(biāo)指引了一些基本決定:多個(gè)類被聚集到一個(gè)單個(gè)的DEX文件。

DEX文件被映射為只讀,并且在進(jìn)程間共享。

針對(duì)本地系統(tǒng)調(diào)整字節(jié)碼順序和詞對(duì)齊。

字節(jié)碼驗(yàn)證對(duì)所有類都是強(qiáng)制的,但我們想要對(duì)一切可能的進(jìn)行”預(yù)驗(yàn)證(pre-verify)”。

需要重寫字節(jié)碼的優(yōu)化必須提前執(zhí)行。

而Dalvik虛擬機(jī)和DEX也就應(yīng)運(yùn)而生。

Hello DEX

讓我們手動(dòng)來(lái)生成一個(gè)java,編譯成javac,然后轉(zhuǎn)換為dex看看:

1

2

3

4

5

6

7echo?'class?Foo?{'\

'public?static?void?main(String[]?args)?{'\

'System.out.println("Hello,?world");?}}'?>?Foo.java

javac?Foo.java

dx?--dex?--output=foo.jar?Foo.class

adb?push?foo.jar?/sdcard/

adb?shell?dalvikvm?-cp?/sdcard/foo.jar?Foo

當(dāng)我們?cè)赿x命令的output中指定輸出文件后綴為.jar,.zip,或者.apk,名為classes.dex的文件就會(huì)被創(chuàng)建并保存在壓縮包內(nèi)。解開(kāi)Foo.jar你就會(huì)看到classes.dex和META-INF文件夾(里面只有一個(gè)MANIFEST.MF文件)。

我們創(chuàng)建完該jar后直接push到設(shè)備上,并通過(guò)shell直接讓dalvik虛擬機(jī)去運(yùn)行它,如果操作無(wú)誤,會(huì)看到命令行的反饋 - Hello, world。

DEX in file system

這次我打算多畫點(diǎn)圖,所以看圖說(shuō)話吧:

DEX in memory

為什么DEX不能被內(nèi)存映射,或者說(shuō),不能直接從zip去執(zhí)行呢?因?yàn)閿?shù)據(jù)是壓縮的,文件頭也不保證是詞對(duì)齊的。這些問(wèn)題可以通過(guò)不壓縮直接保存為classes.dex和填充zip文件來(lái)解決,但會(huì)導(dǎo)致數(shù)據(jù)網(wǎng)絡(luò)間傳輸?shù)陌w積變大。

我們需要在使用前把zip包里的classes.dex解壓。當(dāng)我們拿到文件的時(shí)候,我們可能還會(huì)做些之前提到的其他操作(對(duì)齊、優(yōu)化、驗(yàn)證)。這又引出了另一個(gè)問(wèn)題:誰(shuí)去負(fù)責(zé)做這些,我們又該把輸出放在哪兒?

ODEX是什么

ODEX,全名Optimized DEX,即優(yōu)化過(guò)的DEX。

有至少3種方法去創(chuàng)建一個(gè)“準(zhǔn)備好的”DEX文件,即ODEX:虛擬機(jī)“即時(shí)(just in time)”執(zhí)行。輸出會(huì)跑到一個(gè)特殊的dalvik-cache目錄。這只在一些特殊的桌面和工程機(jī)的設(shè)備上使用(這些機(jī)器的build中,dalvik-cache目錄的權(quán)限不是嚴(yán)格的)。在生產(chǎn)機(jī)器上這是不被允許的。

系統(tǒng)的安裝器在程序首次安裝時(shí)候執(zhí)行,它有寫dalvik-cache的權(quán)限。

構(gòu)建(build)系統(tǒng)預(yù)先執(zhí)行。相關(guān)的 jar / apk 文件還在,但classes.dex被剝離出來(lái)了。ODEX和原來(lái)的zip包保存在一起,不在dalvik-cache,而是系統(tǒng)鏡像的一部分。

dalvik-cache目錄更準(zhǔn)確地說(shuō)是$ANDROID_DATA/data/dalvik-cache。里面的文件的名字來(lái)源于源DEX的完整路徑。在設(shè)備上該目錄被system所擁有,而system擁有0771權(quán)限,保存在那里的ODEX被系統(tǒng)和應(yīng)用的組所擁有,權(quán)限為0644。數(shù)字權(quán)限保護(hù)的應(yīng)用會(huì)使用640權(quán)限來(lái)防止其他應(yīng)用去檢測(cè)它們。底線是你可以讀取自己的與其他大部分應(yīng)用的DEX文件,但你不能創(chuàng)建、修改,或刪除它們。

前兩種方法的執(zhí)行分為以下三個(gè)步驟:

首先,dalvik-cache文件被創(chuàng)建。這必須在一個(gè)有恰當(dāng)權(quán)限的進(jìn)程進(jìn)行,所以在“系統(tǒng)安裝器”的場(chǎng)景,是在運(yùn)行為root的installd進(jìn)程執(zhí)行的。

接著,classes.dex從zip包中解壓出來(lái)。文件頭部留出一小塊空間給ODEX header。

最后,文件被內(nèi)存映射以便訪問(wèn),并被為當(dāng)前系統(tǒng)使用進(jìn)行調(diào)整。這包括了字節(jié)交換(byte-swapping),結(jié)構(gòu)重新排列(structure realigning),但并沒(méi)有對(duì)DEX文件做有意義的改變。還做了一些其他的基本結(jié)構(gòu)檢查,比如確保文件偏移量和數(shù)據(jù)索引落在有效范圍內(nèi)。

構(gòu)建系統(tǒng)不在桌面上運(yùn)行工具,而寧愿去啟動(dòng)模擬器,強(qiáng)制所有相關(guān)DEX文件的即時(shí)優(yōu)化,然后從dalvik-cache把結(jié)果提取出來(lái)。這樣做的原因,在解釋完優(yōu)化后會(huì)變得更顯而易見(jiàn)。

一旦代碼被字節(jié)替換和對(duì)齊,我們就可以繼續(xù)了。我們添加了一些預(yù)計(jì)算的數(shù)據(jù),在文件頭填寫ODEX header,然后開(kāi)始執(zhí)行。然而,如果我們對(duì)驗(yàn)證和優(yōu)化有興趣,就需要在初始準(zhǔn)備后再插入一個(gè)步驟。

dexopt的魔法

在Android 2.3版本以前,系統(tǒng)源碼中提供了生成odex的工具dexopt-wrapper,位于Android 2.2系統(tǒng)源碼的 build/tools/dexpreopt/dexopt-wrapper/ 目錄下,查看DexOptWrapper.cpp文件會(huì)發(fā)現(xiàn)實(shí)際調(diào)用的是 /system/bin/dexopt 程序。在5.0及以上版本的設(shè)備上,你可能已經(jīng)再也找不到dexopt了,取而代之的是dex2oat。

我們想要驗(yàn)證和優(yōu)化DEX文件里的所有類。最簡(jiǎn)單和安全的方法就是把所有類加載到虛擬機(jī),然后跑一遍。任何加載失敗的就是驗(yàn)證/優(yōu)化失敗的。不幸的是,這可能導(dǎo)致一些資源的分配難以釋放(比如native共享庫(kù)的加載),所以我們不想執(zhí)行在應(yīng)用運(yùn)行的虛擬機(jī)里。

解決方案就是起一個(gè)叫做dexopt的程序(事實(shí)上就是虛擬機(jī)的后門)。它會(huì)執(zhí)行一個(gè)簡(jiǎn)短的虛擬機(jī)初始化,從引導(dǎo)的類路徑加載0個(gè)或多個(gè)DEX文件,然后開(kāi)始做一切從目標(biāo)DEX可以做的驗(yàn)證和優(yōu)化。結(jié)束后,進(jìn)程退出,釋放所有資源。

因?yàn)槎鄠€(gè)虛擬機(jī)可能同時(shí)需求同一個(gè)DEX文件,文件鎖被用來(lái)確保dexopt僅被執(zhí)行一次。

驗(yàn)證

字節(jié)碼驗(yàn)證過(guò)程包含了掃描DEX文件中每一個(gè)類每個(gè)方法的指令。目的是為了識(shí)別非法指令序列以便不會(huì)在運(yùn)行時(shí)才發(fā)現(xiàn)它們。涉及到的很多運(yùn)算對(duì)“準(zhǔn)確的”GC也是必要的。更多信息見(jiàn)Dalvik字節(jié)碼驗(yàn)證器筆記。

為了性能原因,(下節(jié)描述的)優(yōu)化器假設(shè)驗(yàn)證器已經(jīng)運(yùn)行成功,還會(huì)做一些其他可能不安全的假設(shè)。默認(rèn)地,Dalvik會(huì)堅(jiān)持驗(yàn)證所有類,并只優(yōu)化那些被驗(yàn)證過(guò)的類。可以使用命令行flags去禁用驗(yàn)證器。怎么在Android應(yīng)用框架中控制這些功能的指令見(jiàn)控制嵌入式虛擬機(jī)。

驗(yàn)證失敗的報(bào)告是一個(gè)復(fù)雜的問(wèn)題。例如,在不同的package中,調(diào)用一個(gè)package內(nèi)可見(jiàn)的方法是非法的,會(huì)被驗(yàn)證器捕捉到。但我們未必想要在驗(yàn)證期報(bào)告它 —— 事實(shí)上我們想要在試圖調(diào)用方法的時(shí)候拋出異常。在每個(gè)方法調(diào)用上檢查這些訪問(wèn)flags也是很昂貴的,Dalvik字節(jié)碼驗(yàn)證器筆記提到了這個(gè)問(wèn)題。

成功被驗(yàn)證的類在ODEX有一個(gè)flag被設(shè)置了,在加載的時(shí)候就不會(huì)被重新驗(yàn)證。ODEX文件有一個(gè)32位的checksum,但那是主要是用來(lái)快速檢查數(shù)據(jù)損壞的。

優(yōu)化

虛擬機(jī)解釋器通常會(huì)在一段代碼被首次使用的時(shí)候執(zhí)行某些優(yōu)化。常量池引用被指向內(nèi)部數(shù)據(jù)結(jié)構(gòu)的指針?biāo)娲?#xff0c;總是成功的操作或是那些總會(huì)以某種方式工作的,會(huì)被更簡(jiǎn)單的形式所替代。這些的一部分需要僅在運(yùn)行時(shí)可用的信息,另一部分在某些特定假設(shè)下可以被靜態(tài)推論出。

Dalvik優(yōu)化器做了這些:對(duì)于虛方法調(diào)用,把方法索引替換為vtable索引。

對(duì)于實(shí)例變量(field)的get/put,把變量索引替換為字節(jié)偏移。另外,把 boolean / byte / char / short 基本變量(variants)合并到單個(gè)的32位形式(解釋器里更少的代碼意味著CPU I-cache里更少的空間)。

替換一些高頻次調(diào)用,比如把 String.length() 替換成”內(nèi)聯(lián)“的。這可以跳過(guò)一些常見(jiàn)的方法調(diào)用消耗,直接從解釋器切換到native實(shí)現(xiàn)。

刪除空方法。最簡(jiǎn)單的例子就是Object.,啥都沒(méi)干,但卻必須在任何對(duì)象被分配的時(shí)候執(zhí)行。指令會(huì)被替換為一個(gè)新版本的空指令(no-op)形式,除非調(diào)試器被attach上去了。

附加預(yù)計(jì)算數(shù)據(jù)。例如,虛擬機(jī)想要一個(gè)類名的哈希表以便查找。不同于在加載DEX文件時(shí)候去計(jì)算這個(gè),我們可以先計(jì)算,以節(jié)省堆(heap)空間和所有加載該DEX文件的虛擬機(jī)的計(jì)算時(shí)間。

大部分的優(yōu)化顯然都會(huì)更好。

Hello ODEX

我們繼續(xù)玩耍之前生成的dex,來(lái)做一個(gè)odex:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20adb?push?dexopt-wrapper?/sdcard/

adb?shell

#?不然沒(méi)權(quán)限去/data/local

su

chmod?777?dexopt-wrapper

#?直接在sdcard執(zhí)行會(huì)提示權(quán)限錯(cuò)誤

cp?dexopt-wrapper?/data/local/

cp?foo.jar?/data/local/

cd?/data/local

/dexopt-wrapper?foo.jar?foo.odex

---?BEGIN?'foo.jar'?(bootstrap=0)?---

---?waiting?for?verify+opt,?pid=5220

---?would?reduce?privs?here

---?END?'foo.jar'?(success)?---

cp?foo.odex?/sdcard

exit

exit

adb?pull?/sdcard/foo.odex?.

這樣子就拿到了優(yōu)化后的odex,趕緊把手機(jī)還給同事。

打開(kāi)App,閱讀手記

總結(jié)

以上是生活随笔為你收集整理的android odex版本调试_Android可执行文件之谜 - DEX与ODEX, OAT与ELF的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: a级黄色网址 | 欧美jizzhd精品欧美18 | 大尺度做爰无遮挡露器官 | 久久久久久久国产精品视频 | 国产伦精品一区二区三区在线 | 中文字幕日本在线 | 女女互慰揉小黄文 | 日韩美女国产精品 | 黑丝美女啪啪 | 日韩另类在线 | 黄av在线播放 | 婷婷五月综合久久中文字幕 | 国内精品一区二区 | 日韩精品免费一区二区三区竹菊 | 五月天爱爱 | 天堂8在线天堂资源bt | 高h奶汁双性受1v1 | 欧美午夜理伦三级在线观看 | 精品中文一区二区三区 | 日日cao | 黑料网在线观看 | 天堂中文字幕在线观看 | 毛片的网站 | 国内精品偷拍视频 | 真实的国产乱xxxx在线91 | 欧美三级韩国三级日本三斤在线观看 | 神马伦理视频 | 亚洲精品图区 | 性色影院 | 亚洲激情自拍 | 精品国产视频一区二区三区 | 国产一区二区三区视频免费观看 | 密臀av| 毛片你懂的 | 找av123导航 67194国产 | hs视频在线观看 | 91久久爱 | 免费在线亚洲 | 黄色污污网站 | 日韩麻豆 | 国产一区二区三区18 | 色伊人影院 | 国产精在线 | 欧美大片一区二区 | 久久无码视频一区 | 国产中文在线 | 91精品国产成人观看 | 国产情侣呻吟对白高潮 | 国产精品日韩一区 | 精品动漫一区二区 | 丝袜脚交免费网站xx | 久久久国| 精品在线视频免费 | 91成人毛片 | 国产黄在线 | 国产亚洲精品自拍 | 嫩草视屏| 视频在线观看 | 免费视频网站在线观看入口 | 国产福利小视频在线观看 | 亚洲国产日韩一区无码精品久久久 | 亚洲精品人妻无码 | 亚洲呦呦 | 欧美精品自拍偷拍 | 国产亚洲欧美日韩高清 | 99视频观看 | 强制憋尿play黄文尿奴 | 亚洲第一在线 | 国产高清在线 | 亚洲精品久久一区二区三区777 | 国产三级大片 | 国产粉嫩在线观看 | 亚洲欧美日韩在线一区二区 | 伊人青草| 日韩影院一区二区 | 久久久久久欧美精品se一二三四 | 亚洲日本在线播放 | 成人av影院在线观看 | 激情国产 | 制服下的诱惑暮生 | www.自拍偷拍| 久国产| 国产欧美日韩成人 | 台湾佬av| 无码精品国产一区二区三区 | 一级片免费在线播放 | 亚洲一区视频在线 | 精品人妻一区二区三区久久夜夜嗨 | 一区二区视频在线看 | 亚洲精品一区中文字幕乱码 | 老司机深夜福利在线观看 | 天天干天天操心 | 朝桐光av一区二区三区 | av女优天堂在线观看 | 精品人妻无码一区二区三区换脸 | 日韩一区二区中文字幕 | 东京av在线 | 国产中文字字幕乱码无限 | 国产尤物在线观看 |