Android虛擬機(jī)與類加載機(jī)制詳情
JVM與Dalvik
Android應(yīng)用程序運(yùn)行在Dalvik/ART虛擬機(jī),并且每一個(gè)應(yīng)用程序?qū)?yīng)有一個(gè)單獨(dú)的Dalvik虛擬機(jī)實(shí)例。Dalvik虛擬機(jī)實(shí)則也算是一個(gè)Java虛擬機(jī),只不過它執(zhí)行的不是class文件,而是dex文件。 Dalvik虛擬機(jī)與Java虛擬機(jī)共享有差不多的特性,差別在于兩者執(zhí)行的指令集是不一樣的,前者的指令集是基本寄存器的,而后者的指令集是基于堆棧的。
JMV基于棧,Dalvik基于寄存器
基于棧的虛擬機(jī)
對于基于棧的虛擬機(jī)來說,每一個(gè)運(yùn)行時(shí)的線程,都有一個(gè)獨(dú)立的棧。棧中記錄了方法調(diào)用的歷史,每有一次方法調(diào)用,棧中便會多一個(gè)棧楨。最頂部的棧楨稱作當(dāng)前棧楨,其代表著當(dāng)前執(zhí)行的方法?;跅5奶摂M機(jī)通過操作數(shù)棧進(jìn)行所有操作。
字節(jié)碼指令
在Androidstudio中搜索ASMPlugin,可以直接用這個(gè)插件查看字節(jié)碼
執(zhí)行過程
基于寄存器的虛擬機(jī)
寄存器
寄存器是CPU的組成部分。寄存器是有限存貯容量的高速存貯部件,它們可用來暫存指令、數(shù)據(jù)和位址。
基于寄存器的虛擬機(jī)
基于寄存器的虛擬機(jī)中沒有操作數(shù)棧,但是有很多虛擬寄存器。其實(shí)和操作數(shù)棧相同,這些寄存器也存放在運(yùn)行時(shí)棧中,本質(zhì)上就是一個(gè)數(shù)組。與JVM相似,在Dalvik VM中每個(gè)線程都有自己的PC和調(diào)用棧,方法調(diào)用的活動記錄以幀為單位保存在調(diào)用棧上。
與JVM版相比,可以發(fā)現(xiàn)Dalvik版程序的指令數(shù)明顯減少了,數(shù)據(jù)移動次數(shù)也明顯減少了。
ART與Dalvik
Dalvik虛擬機(jī)執(zhí)行的是dex字節(jié)碼,解釋執(zhí)行。從Android 2.2版本開始,支持JIT及時(shí)編譯(Just In Time)在程序運(yùn)行的過程中進(jìn)行選擇熱點(diǎn)代碼(經(jīng)常執(zhí)行的代碼)進(jìn)行編譯或者優(yōu)化。 而ART(Android Runtime) 是在 Android 4.4 中引入的一個(gè)開發(fā)者選項(xiàng),也是 Android 5.0 及更高版本的默認(rèn) Android 運(yùn)行時(shí)。ART虛擬機(jī)執(zhí)行的是本地機(jī)器碼。Android的運(yùn)行時(shí)從Dalvik虛擬機(jī)替換成ART虛擬機(jī),并不要求開發(fā)者將自己的應(yīng)用直接編譯成目標(biāo)機(jī)器碼,APK仍然是一個(gè)包含dex字節(jié)碼的文件。那么,ART虛擬機(jī)執(zhí)行的本地機(jī)器碼是從哪里來?
dex2aot
Dalvik下應(yīng)用在安裝的過程,會執(zhí)行一次優(yōu)化,將dex字節(jié)碼進(jìn)行優(yōu)化生成odex文件。而Art下將應(yīng)用的dex字節(jié)碼翻譯成本地機(jī)器碼的最恰當(dāng)AOT時(shí)機(jī)也就發(fā)生在應(yīng)用安裝的時(shí)候。ART 引入了預(yù)先編譯機(jī)制(Ahead Of Time),在安裝時(shí),ART 使用設(shè)備自帶的 dex2oat 工具來編譯應(yīng)用,dex中的字節(jié)碼將被編譯成本地機(jī)器碼。
odex的目的:預(yù)先提取,減少RAM的占用,因?yàn)闆]有odex的話,系統(tǒng)要從apk包中提取dex再運(yùn)行。
dexopt與dexaot
- dexopt:在Dalvik中虛擬機(jī)在加載一個(gè)dex文件時(shí),對 dex 文件 進(jìn)行 驗(yàn)證 和 優(yōu)化的操作,其對 dex 文件的優(yōu)化結(jié)果變成了 odex(Optimized dex) 文件,這個(gè)文件和 dex 文件很像,只是使用了一些優(yōu)化操作碼。
- dex2oat:ART 預(yù)先編譯機(jī)制,在安裝時(shí)對 dex 文件執(zhí)行AOT 提前編譯操作,編譯為OAT(實(shí)際上是ELF文件)可執(zhí)行文件(機(jī)器碼)。
Android N的運(yùn)作方式
ART 使用預(yù)先 (AOT) 編譯,并且從 Android N混合使用AOT編譯,解釋和JIT。 1、最初安裝應(yīng)用時(shí)不進(jìn)行任何 AOT 編譯(安裝又快了),運(yùn)行過程中解釋執(zhí)行,對經(jīng)常執(zhí)行的方法進(jìn)行JIT,經(jīng)過 JIT 編譯的方法將會記錄到Profile配置文件中。 2、當(dāng)設(shè)備閑置和充電時(shí),編譯守護(hù)進(jìn)程會運(yùn)行,根據(jù)Profile文件對常用代碼進(jìn)行 AOT 編譯。待下次運(yùn)行時(shí)直接使用。
ClassLoader
介紹
任何一個(gè) Java 程序都是由一個(gè)或多個(gè) class 文件組成,在程序運(yùn)行時(shí),需要將 class 文件加載到 JVM 中才可以使用,負(fù)責(zé)加載這些 class 文件的就是 Java 的類加載機(jī)制。ClassLoader 的作用簡單來說就是加載 class 文件,提供給程序運(yùn)行時(shí)使用。每個(gè) Class 對象的內(nèi)部都有一個(gè) classLoader 字段來標(biāo)識自己是由哪個(gè)ClassLoader 加載的。
ClassLoader是一個(gè)抽象類,而它的具體實(shí)現(xiàn)類主要有:
- BootClassLoader:用于加載Android Framework層class文件。
- PathClassLoader:用于Android應(yīng)用程序類加載器??梢约虞d指定的dex,以及jar、zip、apk中的classes.dex
- DexClassLoader:用于加載指定的dex,以及jar、zip、apk中的classes.dex
很多博客里說PathClassLoader只能加載已安裝的apk的dex,其實(shí)這說的應(yīng)該是在dalvik虛擬機(jī)上。但現(xiàn)在一般不用關(guān)心dalvik了。
Log.e(TAG, "Activity.class 由:" + Activity.class.getClassLoader() +" 加載"); Log.e(TAG, "MainActivity.class 由:" + getClassLoader() +" 加載"); //輸出: Activity.class 由:java.lang.BootClassLoader@d3052a9 加載 MainActivity.class 由:dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.enjoy.enjoyfix-1/base.apk"],nativeLibraryDirectories= [/data/app/com.enjoy.enjoyfix-1/lib/x86, /system/lib, /vendor/lib]]] 加載
ClassLoader加載流程與雙親委托機(jī)制
可以看到創(chuàng)建 ClassLoader 需要接收一個(gè) ClassLoader parent 參數(shù)。這個(gè) parent 的目的就在于實(shí)現(xiàn)類加載的雙親委托。即: 某個(gè)類加載器在加載類時(shí),首先將加載任務(wù)委托給父類加載器,依次遞歸,如果父 類加載器可以完成類加載任務(wù),就成功返回;只有父類加載器無法完成此加載任務(wù)或者沒有父類加載器時(shí),才自己去加載。
1、避免重復(fù)加載,當(dāng)父加載器已經(jīng)加載了該類的時(shí)候,就沒有必要子ClassLoader再加載一次。 2、安全性考慮,防止核心API庫被隨意篡改。
因此我們自己創(chuàng)建的ClassLoader: new PathClassLoader("/sdcard/xx.dex", getClassLoader()); 并不僅僅只能加載 xx.dex中的class。
值得注意的是: c = findBootstrapClassOrNull(name); 按照方法名理解,應(yīng)該是當(dāng)parent為null時(shí)候,也能夠加載 BootClassLoader 加載的類。 newPathClassLoader("/sdcard/xx.dex", null) ,能否加載Activity.class? 但是實(shí)際上,Android當(dāng)中的實(shí)現(xiàn)為:(Java不同)
類加載
熱修復(fù)
PathClassLoader 中存在一個(gè)Element數(shù)組,Element類中存在一個(gè)dexFile成員表示dex文件,即:APK中有X個(gè)dex,則Element數(shù)組就有X個(gè)元素。
在 PathClassLoader 中的Element數(shù)組為:[patch.dex , classes.dex , classes2.dex]。如果存在Key.class位于patch.dex與classes2.dex中都存在一份,當(dāng)進(jìn)行類查找時(shí),循環(huán)獲得 dexElements 中的DexFile,查找到了Key.class則立即返回,不會再管后續(xù)的element中的DexFile是否能加載到Key.class了。
因此實(shí)際上,一種熱修復(fù)實(shí)現(xiàn)可以將出現(xiàn)Bug的class單獨(dú)的制作一份fix.dex文件(補(bǔ)丁包),然后在程序啟動時(shí),從服務(wù)器下載fix.dex保存到某個(gè)路徑,再通過fix.dex的文件路徑,用其創(chuàng)建 Element 對象,然后將這個(gè) Element 對象插入到我們程序的類加載器 PathClassLoader 的 pathList 中的 dexElements 數(shù)組頭部。這樣在加載出現(xiàn)Bug的class時(shí)會優(yōu)先加載fix.dex中的修復(fù)類,從而解決Bug。
到此這篇關(guān)于Android虛擬機(jī)與類加載機(jī)制詳情的文章就介紹到這了,更多相關(guān)Android虛擬機(jī)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android添加用戶組及自定義App權(quán)限的方法
今天小編就為大家分享一篇Android添加用戶組及自定義App權(quán)限的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-07-07關(guān)于android studio通過命令行運(yùn)行g(shù)radle編譯命令的問題
這篇文章主要介紹了關(guān)于android studio通過命令行運(yùn)行g(shù)radle編譯命令的問題,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-11-11Android側(cè)滑效果簡單實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了Android側(cè)滑效果簡單實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11Android?Camera實(shí)現(xiàn)旋轉(zhuǎn)角度
這篇文章主要為大家詳細(xì)介紹了Android?Camera實(shí)現(xiàn)旋轉(zhuǎn)角度,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07Android實(shí)現(xiàn)Activity界面切換添加動畫特效的方法
這篇文章主要介紹了Android實(shí)現(xiàn)Activity界面切換添加動畫特效的方法,非常實(shí)用的技巧,需要的朋友可以參考下2014-08-08Android Studio實(shí)現(xiàn)華為手機(jī)的充電動畫效果
本篇文章介紹了我參照華為手機(jī)的充電動畫來仿照實(shí)現(xiàn)的樣例,這個(gè)動畫并不難實(shí)現(xiàn),不過案例精簡具有參考意義,需要的朋友快往下看吧2021-10-10Android 按后退鍵退出Android程序的實(shí)現(xiàn)方法
本篇文章介紹了,在Android中按后退鍵退出Android程序的實(shí)現(xiàn)方法。需要的朋友參考下2013-04-04Android Activity啟動模式之singleTop實(shí)例詳解
這篇文章主要介紹了Android Activity啟動模式之singleTop,結(jié)合實(shí)例形式較為詳細(xì)的分析了singleTop模式的功能、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2016-01-01Kotlin?協(xié)程的取消機(jī)制詳細(xì)解讀
這篇文章主要為大家介紹了Kotlin?協(xié)程的取消機(jī)制詳細(xì)解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10Android應(yīng)用圖標(biāo)在狀態(tài)欄上顯示實(shí)現(xiàn)原理
Android應(yīng)用圖標(biāo)在狀態(tài)欄上顯示,以及顯示不同的圖標(biāo),其實(shí)很研究完后,才發(fā)現(xiàn),很簡單,具體實(shí)現(xiàn)如下,感興趣的朋友可以參考下哈2013-06-06