亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android虛擬機(jī)與類加載機(jī)制詳情

 更新時(shí)間:2022年09月06日 09:41:47   作者:havenobug???????  
這篇文章主要介紹了Android虛擬機(jī)與類加載機(jī)制詳情,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下

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)文章

最新評論