精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Android熱修復(fù)技術(shù)總結(jié)

移動(dòng)開發(fā) Android
插件化和熱修復(fù)技術(shù)是Android開發(fā)中比較高級(jí)的知識(shí)點(diǎn),是中級(jí)開發(fā)人員通向高級(jí)開發(fā)中必須掌握的技能,插件化的知識(shí)可以查我我之前的介紹:Android插件化。本篇重點(diǎn)講解熱修復(fù),并對(duì)當(dāng)前流行的熱修復(fù)技術(shù)做一個(gè)簡(jiǎn)單的總結(jié)。

插件化和熱修復(fù)技術(shù)是Android開發(fā)中比較高級(jí)的知識(shí)點(diǎn),是中級(jí)開發(fā)人員通向高級(jí)開發(fā)中必須掌握的技能,插件化的知識(shí)可以查我我之前的介紹:Android插件化。本篇重點(diǎn)講解熱修復(fù),并對(duì)當(dāng)前流行的熱修復(fù)技術(shù)做一個(gè)簡(jiǎn)單的總結(jié)。

熱修復(fù)

什么是熱修復(fù)?

簡(jiǎn)單來講,為了修復(fù)線上問題而提出的修補(bǔ)方案,程序修補(bǔ)過程無(wú)需重新發(fā)版!

技術(shù)背景

在正常軟件開發(fā)流程中,線下開發(fā)->上線->發(fā)現(xiàn)bug->緊急修復(fù)上線。不過對(duì)于這種方式代價(jià)太大。 圖0:Android熱修復(fù)技術(shù)總結(jié)

而熱修復(fù)的開發(fā)流程顯得更加靈活,無(wú)需重新發(fā)版,實(shí)時(shí)高效熱修復(fù),無(wú)需下載新的應(yīng)用,代價(jià)小,最重要的是及時(shí)的修復(fù)了bug。 

圖1:Android熱修復(fù)技術(shù)總結(jié)

當(dāng)前熱門的熱修復(fù)技術(shù)

當(dāng)前熱門的熱修復(fù)技術(shù)有:

  • QQ空間超級(jí)補(bǔ)丁、微信[Tinker]
  • 阿里的Sophix、阿里Hotfix
  • 餓了么Amigo
  • 美團(tuán)Robust
  • 360RePlugin

熱修復(fù)技術(shù)

要弄清熱修復(fù)技術(shù)的原理,就要先弄清Android的ClassLoader機(jī)制,相關(guān)文章可以閱讀之前的介紹:ClassLoader類加載機(jī)制。Android的ClassLoader分為PathClassLoader和DexClassLoader,它們都都繼承自BaseDexClassLoader,其中PathClassLoader用來加載系統(tǒng)類和應(yīng)用類;DexClassLoader用來加載jar、apk、dex文件。例如下面要介紹的阿里的Andfix和Sophix的原理如下:

AndFix

AndFix:由補(bǔ)丁類的classLoader加載補(bǔ)丁類,在native層針對(duì)不同Android架構(gòu)中的不同的ArtMethod結(jié)構(gòu)調(diào)用對(duì)應(yīng)的replaceMethod方法按照定義好的ArtMethod結(jié)構(gòu)一一替換方法的所有信息如所屬類、訪問權(quán)限、代碼內(nèi)存地址等。

穩(wěn)定性較差,會(huì)受到國(guó)內(nèi)ROM廠商對(duì)ArtMethod結(jié)構(gòu)更改的影響,所以這正是AndFix不支持很多機(jī)型的原因。

Sophix

Sophix:由補(bǔ)丁類的classLoader加載補(bǔ)丁類,在native層直接memcpy(smeth,dmth,sizeof(ArtMethod))替換整個(gè)artMethod的結(jié)構(gòu)。初始化類時(shí)會(huì)為這個(gè)類分配空間,AllocArtMethodArray會(huì)緊挨著的new出來放入art中的方法數(shù)組中。通過計(jì)算輔助類的前后兩個(gè)方法的起始地址就可以計(jì)算出artMethod結(jié)構(gòu)的大小了。

注:補(bǔ)丁類初始化時(shí),也會(huì)分配自己的artMethod空間,拿這個(gè)修復(fù)過的新ArtMethod去替換舊ArtMethod的內(nèi)容,不用管ArtMethod的結(jié)構(gòu)。穩(wěn)定性大大提高!

java

內(nèi)部類編譯

靜態(tài)內(nèi)部類/非靜態(tài)內(nèi)部類區(qū)別

內(nèi)部類會(huì)被編譯器生成同外部類一樣的頂級(jí)類。只不過非靜態(tài)內(nèi)部類會(huì)持有外部類的引用。這也是Android性能優(yōu)化建議Handler使用靜態(tài)內(nèi)部類,防止外部類Activity不能被回收導(dǎo)致造成OOM。

內(nèi)部類和外部類互相訪問

內(nèi)部類和外部類互相訪問private方法和字段時(shí),會(huì)自動(dòng)在對(duì)應(yīng)類為對(duì)方生成public的access&**方法。

熱部署解決方案

外部類如果有內(nèi)部類把所有的field/method的private訪問權(quán)限改成proteced或者public內(nèi)部類將所有的field/method的private訪問權(quán)限改成proteced或者public。

匿名內(nèi)部類編譯

匿名內(nèi)部類命名規(guī)則

外部類&number。number即編譯器根據(jù)匿名內(nèi)部類出現(xiàn)在外部類中的順序,依次累加。

熱部署解決方案

新增/減少匿名內(nèi)部類對(duì)熱部署是無(wú)解的,因?yàn)檠a(bǔ)丁修復(fù)工具拿到的是class文件,無(wú)法區(qū)別DexFileDemo&1和DexFileDemo&2,會(huì)導(dǎo)致類的順序亂套。如果匿名內(nèi)部類插入到末尾則是允許。

域編譯

靜態(tài)field,非靜態(tài)field編譯

熱部署不支持field/method增加和刪除和 clinit方法的修改,靜態(tài)field的初始化和靜態(tài)代碼塊會(huì)被編譯在編譯器合成的方法clinit中,非靜態(tài)字段的初始化會(huì)被編譯在編譯器生成的init無(wú)參構(gòu)造函數(shù)中,

靜態(tài)field,靜態(tài)代碼塊

clinit方法會(huì)在類加載階段的類初始化時(shí)調(diào)用,clinit中靜態(tài)field和靜態(tài)代碼塊的出現(xiàn)順序就是二者在源碼中出現(xiàn)的順序。因?yàn)轭愐呀?jīng)加載過了,所以就算修復(fù)了clinit方法也不會(huì)生效了。

dvmResolveClass->dvmLinkClass->dvmInitClass,然后執(zhí)行clinit方法

以下情況會(huì)去加載一個(gè)類

  1. new 一個(gè)類的對(duì)象時(shí)new instance
  2. 調(diào)用類的靜態(tài)方法(invoke static)
  3. 獲取類的靜態(tài)域的值(sget)

非靜態(tài)field,非靜態(tài)代碼塊

類的構(gòu)造函數(shù)會(huì)被編譯器翻譯成init方法,會(huì)先進(jìn)行非靜態(tài)field和非靜態(tài)代碼塊的初始化。它們出現(xiàn)的順序也是和在源碼中出現(xiàn)的順序一樣。

執(zhí)行new instance指令時(shí),如果類沒有加載過,就嘗試加載類。然后對(duì)對(duì)象內(nèi)存分配,再然后執(zhí)行invoke direct指令調(diào)用類的init構(gòu)造函數(shù)進(jìn)行初始化

熱部署解決方案

不支持對(duì)靜態(tài)字段和靜態(tài)代碼塊的修改,會(huì)導(dǎo)致熱部署失敗,只能冷啟動(dòng)生效。支持非靜態(tài)字段和非靜態(tài)代碼塊修改,熱部署只是將init構(gòu)造函數(shù)作為普通的方法變更。

final static 域編譯

final static 域編譯規(guī)則

final static引用類型初始化仍在clinit中final static基本類型和String類型,類加載初始化dvminitClass在執(zhí)行clinit方法之前,先執(zhí)行initSFields,這個(gè)方法為static域賦予默認(rèn)值。引用類型默認(rèn)NULL,final static修飾的基本類型和String類型會(huì)在這里初始化賦值。

final static 域優(yōu)化原理

  • inal static基本類型執(zhí)行const/4指令,操作數(shù)在dex中的位置(encoded_array_item)就是在opcode后一個(gè)字節(jié)。
  • final static String類型執(zhí)行const-string指令,本質(zhì)同上只不過拿到的是字符串常量在dex文件結(jié)構(gòu)中字符串常量區(qū)的索引id。dex文件有一塊區(qū)域存儲(chǔ)所有的字符串常量會(huì)被完整的加載到虛擬機(jī)內(nèi)存中-字符串常量區(qū)。
  • final static引用類型執(zhí)行sget指令,首先調(diào)用dvmDexGetResolveField看這個(gè)域是否之前解析過,沒有的話調(diào)用dvmDexResolveField嘗試解析域,如果這個(gè)靜態(tài)域所在的類沒有解析過,嘗試調(diào)用dvmResolveClass,拿到這個(gè)sField,然后通過dvmDexGetResolveField(sField)獲取這個(gè)靜態(tài)值。

熱部署解決方案

  • final static基本類型/string類型最終引用的類型會(huì)被熱部署替換掉。
  • final static引用類型因?yàn)闀?huì)被翻譯到clinit方法中,熱部署失敗。

泛型編譯

為什么需要泛型

Java泛型完全有編譯器實(shí)現(xiàn),由編譯器執(zhí)行類型檢查和類型推斷,生成非泛型字節(jié)碼,稱之為擦除。

沒有泛型之前想要實(shí)現(xiàn)類泛型,利用所有類的父類時(shí)Object進(jìn)行強(qiáng)轉(zhuǎn),這完全依賴程序員的自主性,很容易出現(xiàn)ClassCastException。泛型的出現(xiàn)解決了類型檢查和類型推斷的問題。

泛型類型擦除

Java字節(jié)碼中不包含泛型類型信息,想要區(qū)別類型定義可以限定泛型類型

類型擦除與多態(tài)的沖突和解決

父類是泛型類有setNumber(T value),子類想override setNumber(Number value)。然而實(shí)際父類的方法實(shí)際是setNumber(Object value),子類想重寫卻變成了重載,這就出現(xiàn)了類型擦除和多態(tài)之間的沖突。然而編譯器自動(dòng)幫我們合成了Bridge方法實(shí)現(xiàn)了重載,在子類中生成了相同簽名bridge方法,內(nèi)部實(shí)際調(diào)用子類的重寫方法。

泛型類型轉(zhuǎn)換

編譯器如果發(fā)現(xiàn)變量聲明加上了泛型信息,編譯器自動(dòng)加上了check-cast的強(qiáng)制轉(zhuǎn)換,因?yàn)榫幾g器會(huì)為泛型做類型檢查,所以自動(dòng)的強(qiáng)制轉(zhuǎn)換不會(huì)出現(xiàn)ClassCastException。

熱部署解決方案

如果父類補(bǔ)丁變成了增加了泛型則會(huì)增加Bridge方法,造成熱部署失敗。

將方法從void get(B t) 變成 B extends Number void get(B t)方法邏輯不會(huì)發(fā)生變化,但是方法的簽名會(huì)發(fā)生變化,這種情況熱修復(fù)沒有意義,需要避免這種情況的發(fā)生。

Lambda表達(dá)式編譯

Lambda表達(dá)式編譯規(guī)則

Lamda表達(dá)式具有函數(shù)式編程的特點(diǎn),是Java中最接近閉包的概念。函數(shù)式接口:一個(gè)接口具有唯一一個(gè)抽象方法

Java中的Runable和Comparator都是典型的函數(shù)式接口

Lamada表達(dá)式和匿名內(nèi)部類的區(qū)別:

  1. this關(guān)鍵字指包圍Lamada表達(dá)式的類而不是指向匿名內(nèi)部類自己
  2. 編譯方式,Java編譯器將Lamda表達(dá)式編譯成類的私有方法,使用了Java7的invokedynamic動(dòng)態(tài)綁定這個(gè)私有方法。而匿名內(nèi)部類則是生成外部類&number的新類.編譯器都會(huì)在類下生成lamdamain*{ }私有靜態(tài)方法,這個(gè)方法實(shí)現(xiàn)了lamda表達(dá)式的邏輯,引用的變量都會(huì)變成方法的參數(shù)。

在HostSpot VM下解釋class文件的lamda表達(dá)式:

  • invokeDynamic指令調(diào)用java/lang/invoke/LamdaMetafactory的metafactory這個(gè)靜態(tài)方法。這個(gè)方法會(huì)在運(yùn)行時(shí)生成實(shí)現(xiàn)函數(shù)式接口的具體類,這個(gè)具體類會(huì)調(diào)用那個(gè)靜態(tài)私有方法。
  • 在Android虛擬機(jī)下解釋dex文件中的lamda表達(dá)式:則是在優(yōu)化成dex文件的時(shí)候就生成了這個(gè)具體類。

熱部署解決方案

新增lamada表達(dá)式會(huì)導(dǎo)致外部類新增一個(gè)輔助方法。修改的lamda表達(dá)式邏輯引用了外部變量,會(huì)導(dǎo)致輔助類持有了外部對(duì)象,會(huì)新增這個(gè)外部對(duì)象的變量。也是會(huì)導(dǎo)致熱修復(fù)失敗。

Sophix與QQ超級(jí)補(bǔ)丁和Tinker技術(shù)比較

針對(duì)現(xiàn)在市面上比較流行的熱修復(fù)方案,這里選擇Sophix、QQ超級(jí)補(bǔ)丁和Tinker進(jìn)行簡(jiǎn)單的介紹。前面說過,類似于qq空間和微信的實(shí)現(xiàn)方式都需要重新啟動(dòng)才能修復(fù)bug,而阿里的Sophix采用的是非浸入式的方式不需要冷啟動(dòng)。

QQ空間超級(jí)補(bǔ)丁

QQ空間超級(jí)補(bǔ)丁采用的插樁方式,入侵打包流程,單獨(dú)放一個(gè)幫助類在獨(dú)立的dex中讓其他類調(diào)用,阻止類在dexopt時(shí)被打傷CLASS_ISPREVERIFIED標(biāo)記。其原理如下圖: 

圖2:Android熱修復(fù)技術(shù)總結(jié)

加載補(bǔ)丁dex得到dexFile對(duì)象作為參數(shù)構(gòu)建一個(gè)Element對(duì)象插入到dexElement數(shù)組最前面。

Tinker提供差量包,整體替換dex的方案。將patch.dex與應(yīng)用的class.dex合并生成一個(gè)完整的dex,加載完整的dex得到dexFile對(duì)象為參數(shù)構(gòu)建一個(gè)Element對(duì)象替換dexElements數(shù)組。

官方multiDex沒有補(bǔ)丁查詢更新,下載補(bǔ)丁待下次啟動(dòng)時(shí)生效。

其流程可以總結(jié)為如下圖所示: 

圖3:Android熱修復(fù)技術(shù)總結(jié)

不過細(xì)心的讀者會(huì)發(fā)現(xiàn),QQ空間超級(jí)補(bǔ)丁在使用 過程中還存在如下問題:

  1. 不支持即時(shí)生效,必須通過重啟才能生效。
  2. 為了實(shí)現(xiàn)修復(fù)這個(gè)過程,必須在應(yīng)用中加入兩個(gè)dex!dalvikhack.dex中只有一個(gè)類,對(duì)性能影響不大,但是對(duì)于patch.dex來說,修復(fù)的類到了一定數(shù)量,就需要花不少的時(shí)間加載。對(duì)手淘這種航母級(jí)應(yīng)用來說,啟動(dòng)耗時(shí)增加2s以上是不能夠接受的事。
  3. 在ART模式下,如果類修改了結(jié)構(gòu),就會(huì)出現(xiàn)內(nèi)存錯(cuò)亂的問題。為了解決這個(gè)問題,就必須把所有相關(guān)的調(diào)用類、父類子類等等全部加載到patch.dex中,導(dǎo)致補(bǔ)丁包異常的大,進(jìn)一步增加應(yīng)用啟動(dòng)加載的時(shí)候,耗時(shí)更加嚴(yán)重。

針對(duì)上面的問題,騰訊出了QFix方案。

在native層提前調(diào)用dvmResolveClass,是的在dvmResolve中調(diào)用dvmDexGetResolve不為null,也避免了校驗(yàn)一致性的問題。

這個(gè)方案要求傳遞的在多dex情況下,referrer類必須跟patch類是同一個(gè)dex。fromUnverifiedConstant必須為true。referrer必須提前加載。

這方案還要一些問題,在dexopt之后繞過,但是dexopt會(huì)改變很多原先的邏輯,許多odex層面的優(yōu)化會(huì)寫死字段和訪問方法的偏移。這會(huì)造成很嚴(yán)重的BUG。

微信Tinker

微信針對(duì)QQ空間超級(jí)補(bǔ)丁技術(shù)的不足提出了一個(gè)提供DEX差量包,整體替換DEX的方案。主要的原理是與QQ空間超級(jí)補(bǔ)丁技術(shù)基本相同,區(qū)別在于不再將patch.dex增加到elements數(shù)組中,而是差量的方式給出patch.dex,然后將patch.dex與應(yīng)用的classes.dex合并,然后整體替換掉舊的DEX文件,以達(dá)到修復(fù)的目的。其原理圖如下:

Android熱修復(fù)技術(shù)總結(jié)

微信的熱修復(fù)的流程如圖所示: 

圖5:Android熱修復(fù)技術(shù)總結(jié)

不過微信的方案仍然會(huì)有如下問題:

  1. 與超級(jí)補(bǔ)丁技術(shù)一樣,不支持即時(shí)生效,必須通過重啟應(yīng)用的方式才能生效。
  2. 需要給應(yīng)用開啟新的進(jìn)程才能進(jìn)行合并,并且很容易因?yàn)閮?nèi)存消耗等原因合并失敗。
  3. 合并時(shí)占用額外磁盤空間,對(duì)于多DEX的應(yīng)用來說,如果修改了多個(gè)DEX文件,就需要下發(fā)多個(gè)patch.dex與對(duì)應(yīng)的classes.dex進(jìn)行合并操作時(shí)這種情況會(huì)更嚴(yán)重,因此合并過程的失敗率也會(huì)更高。

HotFix

阿里的HotFix方案,相對(duì)于QQ空間超級(jí)補(bǔ)丁技術(shù)和微信Tinker來說,定位于緊急BUG修復(fù)的場(chǎng)景下,能夠最及時(shí)的修復(fù)BUG,下拉補(bǔ)丁立即生效無(wú)需等待。 

圖6:Android熱修復(fù)技術(shù)總結(jié)

AndFix不同于QQ空間超級(jí)補(bǔ)丁技術(shù)和微信Tinker通過增加或替換整個(gè)DEX的方案,提供了一種運(yùn)行時(shí)在Native修改Filed指針的方式,實(shí)現(xiàn)方法的替換,達(dá)到即時(shí)生效無(wú)需重啟,對(duì)應(yīng)用無(wú)性能消耗的目的。其原理如下:

 

圖7:Android熱修復(fù)技術(shù)總結(jié)

對(duì)于實(shí)現(xiàn)方法的替換,需要在Native層操作,主要經(jīng)過三個(gè)步驟:

Android熱修復(fù)技術(shù)總結(jié)

不過HotFix也有不足:

  1. 不支持新增字段,以及修改方法,也不支持對(duì)資源的替換。
  2. 由于廠商的自定義ROM,對(duì)少數(shù)機(jī)型暫不支持。兼容性差。

綜上,對(duì)于上面的幾種框架技術(shù)總結(jié)如下:

Android熱修復(fù)技術(shù)總結(jié)

熱修復(fù)方案總結(jié)

代碼修復(fù)有兩大主要方案:一種是阿里系的底層替換方案,另一種是騰訊系的類加載方案。底層替換方案限制頗多,但時(shí)效性最好,加載輕快,立即見效。類加載方案時(shí)效性差,需要重新冷啟動(dòng)才能見效,但修復(fù)范圍廣,限制少。

底層替換方案

底層替換方案是在已經(jīng)加載了的類中直接替換掉原有方法,是在原來類的基礎(chǔ)上進(jìn)行修改的。因而無(wú)法實(shí)現(xiàn)對(duì)與原有類進(jìn)行方法和字段的增減,因?yàn)檫@樣將破壞原有類的結(jié)構(gòu)。

一旦補(bǔ)丁類中出現(xiàn)了方法的增加和減少,就會(huì)導(dǎo)致這個(gè)類以及整個(gè)Dex的方法數(shù)的變化。方法數(shù)的變化伴隨著方法索引的變化,這樣在訪問方法時(shí)就無(wú)法正常地索引到正確的方法了。

如果字段發(fā)生了增加和減少,和方法變化的情況一樣,所有字段的索引都會(huì)發(fā)生變化。并且更嚴(yán)重的問題是,如果在程序運(yùn)行中間某個(gè)類突然增加了一個(gè)字段,那么對(duì)于原先已經(jīng)產(chǎn)生的這個(gè)類的實(shí)例,它們還是原來的結(jié)構(gòu),這是無(wú)法改變的。而新方法使用到這些老的實(shí)例對(duì)象時(shí),訪問新增字段就會(huì)產(chǎn)生不可預(yù)期的結(jié)果。

這是這類方案的固有限制,而底層替換方案最為人詬病的地方,在于底層替換的不穩(wěn)定性。

傳統(tǒng)的底層替換方式,不論是Dexposed、Andfix或者其他安全界的Hook方案,都是直接依賴修改虛擬機(jī)方法實(shí)體的具體字段。例如,改Dalvik方法的jni函數(shù)指針、改類或方法的訪問權(quán)限等等。這樣就帶來一個(gè)很嚴(yán)重的問題,由于Android是開源的,各個(gè)手機(jī)廠商都可以對(duì)代碼進(jìn)行改造,而Andfix里ArtMethod的結(jié)構(gòu)是根據(jù)公開的Android源碼中的結(jié)構(gòu)寫死的。如果某個(gè)廠商對(duì)這個(gè)ArtMethod結(jié)構(gòu)體進(jìn)行了修改,就和原先開源代碼里的結(jié)構(gòu)不一致,那么在這個(gè)修改過了的設(shè)備上,通用性的替換機(jī)制就會(huì)出問題。這便是不穩(wěn)定的根源。

而我們也對(duì)代碼的底層替換原理重新進(jìn)行了深入思考,從克服其限制和兼容性入手,以一種更加優(yōu)雅的替換思路,實(shí)現(xiàn)了即時(shí)生效的代碼熱修復(fù)。sophix實(shí)現(xiàn)的是一種無(wú)視底層具體結(jié)構(gòu)的替換方式,也就是把原先這樣的逐一替換:

這么一來,我們不僅解決了兼容性問題,并且由于忽略了底層ArtMethod結(jié)構(gòu)的差異,對(duì)于所有的Android版本都不再需要區(qū)分,代碼量大大減少。即使以后的Android版本不斷修改ArtMethod的成員,只要保證ArtMethod數(shù)組仍是以線性結(jié)構(gòu)排列,就能直接適用于將來的Android 8.0、9.0等新版本,無(wú)需再針對(duì)新的系統(tǒng)版本進(jìn)行適配了。

類加載方案

類加載方案的原理是在app重新啟動(dòng)后讓Classloader去加載新的類。因?yàn)樵赼pp運(yùn)行到一半的時(shí)候,所有需要發(fā)生變更的類已經(jīng)被加載過了,在Android上是無(wú)法對(duì)一個(gè)類進(jìn)行卸載的。如果不重啟,原來的類還在虛擬機(jī)中,就無(wú)法加載新類。因此,只有在下次重啟的時(shí)候,在還沒走到業(yè)務(wù)邏輯之前搶先加載補(bǔ)丁中的新類,這樣后續(xù)訪問這個(gè)類時(shí),就會(huì)Resolve為新類。從而達(dá)到熱修復(fù)的目的。

再來看看騰訊系三大類加載方案的實(shí)現(xiàn)原理。QQ空間方案會(huì)侵入打包流程,并且為了hack添加一些無(wú)用的信息,實(shí)現(xiàn)起來很不優(yōu)雅。而QFix的方案,需要獲取底層虛擬機(jī)的函數(shù),不夠穩(wěn)定可靠,并且有個(gè)比較大的問題是無(wú)法新增public函數(shù)。

微信的Tinker方案是完整的全量dex加載,并且可謂是將補(bǔ)丁合成做到了極致,然而我們發(fā)現(xiàn),精密的武器并非適用于所有戰(zhàn)場(chǎng)。Tinker的合成方案,是從dex的方法和指令維度進(jìn)行全量合成,整個(gè)過程都是自己研發(fā)的。

雖然可以很大地節(jié)省空間,但由于對(duì)dex內(nèi)容的比較粒度過細(xì),實(shí)現(xiàn)較為復(fù)雜,性能消耗比較嚴(yán)重。實(shí)際上,dex的大小占整個(gè)apk的比例是比較低的,一個(gè)app里面的dex文件大小并不是主要部分,而占空間大的主要還是資源文件。因此,Tinker方案的時(shí)空代價(jià)轉(zhuǎn)換的性價(jià)比不高。

其實(shí),dex比較的最佳粒度,應(yīng)該是在類的維度。它既不像方法和指令維度那樣的細(xì)微,也不像bsbiff比較那般的粗糙。在類的維度,可以達(dá)到時(shí)間和空間平衡的最佳效果。基于這個(gè)準(zhǔn)則,我們另辟蹊徑,實(shí)現(xiàn)了一種完全不同的全量dex替換方案。

sophix采用的也是全量合成dex的技術(shù),這個(gè)技術(shù)是從手淘插件化框架Atlas汲取的。直接利用Android原先的類查找和合成機(jī)制,快速合成新的全量dex。這么一來,我們既不需要處理合成時(shí)方法數(shù)超過的情況,對(duì)于dex的結(jié)構(gòu)也不用進(jìn)行破壞性重構(gòu)。 

圖10:Android熱修復(fù)技術(shù)總結(jié)

從圖中可以看到,我們重新編排了包中dex的順序。這樣,在虛擬機(jī)查找類的時(shí)候,會(huì)優(yōu)先找到classes.dex中的類,然后才是classes2.dex、classes3.dex,也可以看做是dex文件級(jí)別的類插樁方案。這個(gè)方式十分巧妙,它對(duì)舊包與補(bǔ)丁包中classes.dex的順序進(jìn)行了打破與重組,最終使得系統(tǒng)可以自然地識(shí)別到這個(gè)順序,以實(shí)現(xiàn)類覆蓋的目的。這將會(huì)大大減少合成補(bǔ)丁的開銷。

資源修復(fù)

在Android熱修復(fù)的過程中,不僅需要對(duì)錯(cuò)誤的代碼進(jìn)行修復(fù),還需要對(duì)資源文件進(jìn)行修復(fù)。目前市面上的資源熱修復(fù)方案基本上都是參考Instant Run的實(shí)現(xiàn)。Instant Run實(shí)現(xiàn)過程大概分為兩部:

  1. 構(gòu)造一個(gè)新的AssetManager,并通過反射條用addAssetPath,把這個(gè)完整的新資源包加入到AssetManager中。這樣就得到了一個(gè)含有所有新資源的AssetManager。
  2. 找到所有之前引用到原AssetManager的地方,通過反射,把引用處替換為AssetManager

這種方式下發(fā)完整的包很占用空間。而像有些方案,是先進(jìn)行對(duì)資源包做差量,在運(yùn)行時(shí)合成完整包再加載。這樣確實(shí)減少包的體積,但是在運(yùn)行時(shí)多了合成的操作,耗費(fèi)了運(yùn)行時(shí)間喝內(nèi)存。合成后的包也是完整的包,仍舊會(huì)占磁盤空間。

so庫(kù)修復(fù)

so庫(kù)的修復(fù)本質(zhì)上是對(duì)native方法的修復(fù)和替換。我們知道在JNI編程中,native方法可以通過動(dòng)態(tài)注冊(cè)和靜態(tài)注冊(cè)兩種方式進(jìn)行。動(dòng)態(tài)注冊(cè)的native方法必須實(shí)現(xiàn)JNI_OnLoad方法,同時(shí)實(shí)現(xiàn)一個(gè)JNINativeMethod[]數(shù)組,靜態(tài)注冊(cè)的native方法必須是Java+類完整路徑+方法名的格式。 

圖11:Android熱修復(fù)技術(shù)總結(jié)

動(dòng)態(tài)注冊(cè)的native方法映射通過加載so庫(kù)過程中調(diào)用JNI_OnLoad方法調(diào)用完成,靜態(tài)注冊(cè)的native方法映射是在該native方法第一次執(zhí)行的時(shí)候才完成映射,當(dāng)然前提是該so庫(kù)已經(jīng)load過。

我們采用的是類似類修復(fù)反射注入方式。把補(bǔ)丁so庫(kù)的路徑插入到nativeLibraryDirectories數(shù)組的最前面,就能夠達(dá)到加載so庫(kù)的時(shí)候是補(bǔ)丁so庫(kù),而不是原來so庫(kù)的目錄,從而達(dá)到修復(fù)的目的。 

圖12:Android熱修復(fù)技術(shù)總結(jié)
責(zé)任編輯:未麗燕 來源: 程序師
相關(guān)推薦

2011-03-29 15:15:06

熱備份熱修復(fù)

2016-10-28 10:40:12

2016-10-11 14:09:33

2021-10-24 06:50:52

AndroidClassLoaderJava

2017-06-14 10:12:19

SophixAndroid熱修復(fù)

2015-08-25 08:57:57

android6.0技術(shù)總結(jié)

2015-03-17 19:35:49

Xen漏洞阿里云

2011-08-19 15:04:11

Windows7熱修復(fù)補(bǔ)丁

2009-06-01 13:37:47

jpa技術(shù)總結(jié)ejb

2013-11-12 09:39:41

IGMP組播

2019-11-11 10:38:06

日志配置技術(shù)

2017-11-28 15:36:25

換扶技術(shù)Android資源

2016-12-16 20:04:44

2015-05-20 13:06:03

2017-01-10 19:06:39

Android日常開發(fā)技術(shù)經(jīng)驗(yàn)

2017-06-07 18:59:21

2014-11-03 17:52:00

NEC人臉修復(fù)技術(shù)

2023-04-14 15:07:05

架構(gòu)開發(fā)自動(dòng)化工具

2017-08-28 14:43:28

Kubernetes技術(shù)紅帽

2011-08-24 13:24:52

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

极品少妇xxxx精品少妇| 亚洲黄页网站| 粉嫩老牛aⅴ一区二区三区| 精品久久久久久综合日本| 销魂美女一区二区| 国产精品二区不卡| 视频在线不卡免费观看| 精品一区二区在线观看| 97视频在线观看免费| 人妻少妇无码精品视频区| 欧一区二区三区| 在线观看日韩毛片| 国产手机免费视频| 在线看的av网站| 91丨九色丨尤物| 亚洲综合在线小说| 中文字幕天堂在线| 极品少妇一区二区三区| 中文字幕综合在线| 中文字幕一区二区三区人妻不卡| www一区二区三区| 色久优优欧美色久优优| 日韩精品一区在线视频| 黄色成年人视频在线观看| 久久亚洲精精品中文字幕早川悠里 | 精品成人久久| 久久精品国产亚洲一区二区| 高潮毛片无遮挡| 国产精品久久久久久久av| 影音先锋中文在线视频| 国产欧美一区二区三区鸳鸯浴| av一区二区三区免费| 亚洲一区二区色| 久久影院亚洲| 欧美一级成年大片在线观看| 久久婷婷一区二区| 亚洲精品成人| 日韩亚洲欧美中文高清在线| 色婷婷在线影院| 人人精品视频| 亚洲精品久久久一区二区三区 | 久久精品亚洲无码| 91精品综合| 日韩天堂在线视频| 精品一区二区6| 精品国产一区二区三区av片| 亚洲码在线观看| 亚洲天堂资源在线| 欧美尿孔扩张虐视频| 亚洲国产小视频| 强迫凌虐淫辱の牝奴在线观看| 高潮久久久久久久久久久久久久| 日韩欧美国产综合| 国产亚洲精品成人a| 精品一区二区三区亚洲| 日韩一区二区在线看片| 少妇高潮一69aⅹ| 在线精品自拍| 亚洲成人激情在线| 五月开心播播网| 亚洲日本三级| 色偷偷偷综合中文字幕;dd| 一二三四国产精品| 国产精品久久久久9999赢消| 久久精品精品电影网| 天天操夜夜操av| 女生裸体视频一区二区三区| 国模吧一区二区| 成人精品在线看| 日韩精品五月天| 国产精品专区一| 国产熟女一区二区三区五月婷| 国产一区在线精品| 国产日韩亚洲精品| 精品视频二区| aa视频在线免费观看| 国产精品日韩欧美一区| 日韩免费观看网站| 亚洲网站免费观看| 国产大陆精品国产| 精品久久一区二区三区蜜桃| 黄色电影免费在线看| 欧美激情一区三区| 污污污污污污www网站免费| 91av久久| 欧美丝袜丝交足nylons| 色诱av手机版| 欧美男同视频网| 久久艹在线视频| 国产又黄又粗又爽| 精品一区二区久久久| 国产66精品久久久久999小说| 天堂91在线| 亚洲欧洲精品天堂一级| www在线观看免费| 成人四虎影院| 亚洲成人久久一区| 在线观看免费小视频| 一区免费视频| 国产综合福利在线| 天堂a√中文在线| 亚洲黄色录像片| 88av.com| 欧美理论电影在线精品| 久久精品人人做人人爽| 91精品国产综合久久久蜜臀九色| 国产制服丝袜一区| 日本一区二区三区四区高清视频| 欧美性猛片xxxxx免费中国| 欧洲视频一区二区| 国产真实乱人偷精品| 99久久夜色精品国产亚洲狼| 欧洲美女7788成人免费视频| 国产黄色片网站| 中文字幕 久热精品 视频在线| av免费观看国产| 欧美成年网站| 日韩在线高清视频| 尤物视频免费观看| 99国产精品久久久久久久久久久| 亚洲国产欧美日韩| 夜鲁夜鲁夜鲁视频在线播放| 精品国产免费一区二区三区四区 | 1区2区3区国产精品| 国产精品wwwww| 欧美a一欧美| 久久久爽爽爽美女图片| 国产成人毛毛毛片| 亚洲丝袜自拍清纯另类| 欧美大尺度做爰床戏| 亚洲aa在线| 8x海外华人永久免费日韩内陆视频| 国产人妖一区二区| **欧美大码日韩| 欧美疯狂做受xxxx高潮| 久久露脸国语精品国产91| 国产又粗又猛又爽又黄91精品| 亚洲一区二区三区加勒比| 亚洲欧美电影| 亚洲欧美国产一本综合首页| 国产精品男女视频| 91在线观看污| 男人日女人逼逼| 青草久久视频| 日本久久久久久久久久久| 男操女在线观看| 日本高清不卡在线观看| 老熟妇一区二区| 日本不卡免费在线视频| 午夜老司机精品| 久久亚洲国产精品尤物| 中文字幕一区二区精品| 91成人一区二区三区| 综合分类小说区另类春色亚洲小说欧美| 午夜剧场在线免费观看| 欧美777四色影| 成人av影视在线| 波多野结依一区| 日韩成人在线视频网站| 国产精品久久久久久久妇| 久久综合网色—综合色88| 少妇高清精品毛片在线视频| 久久高清免费| 亚洲最大的网站| 日本无删减在线| 亚洲第一天堂av| 色一情一乱一伦| 国产精品蜜臀av| 青娱乐国产精品视频| 在线欧美福利| 欧美不卡福利| 欧美xxxx网站| 欧美激情一区二区三区久久久| 熟妇人妻一区二区三区四区 | 欧美亚洲国产精品| 国产天堂在线| 欧美一区二区三级| 精品人妻一区二区免费视频| 亚洲视频精品| 欧美老女人第四色| 国产成人精品视频免费| 国产一区激情在线| 亚洲色成人www永久在线观看| 欧美日韩导航| 日本久久久久久久| 在线视频91p| 亚洲欧美综合久久久久久v动漫| 中文字幕欧美一区| 亚洲av无一区二区三区久久| 国产一区二区你懂的| 亚洲一卡二卡区| 欧美日韩成人综合在线一区二区| 日本一区免费看| 欧美男男gaygay1069| 久久国产精品影片| 日韩偷拍自拍| 91精品黄色片免费大全| 日本成人黄色免费看| 午夜日韩成人影院| 久久久国产成人精品| 天天干在线观看| 欧美日韩五月天| 国产精品老女人| 亚洲天堂免费看| 日本一级免费视频| 99久久久无码国产精品| 做a视频在线观看| 久久99伊人| 中文字幕の友人北条麻妃| 精品在线观看入口| 国产日本一区二区三区| 欧美成人一级| 国产视频999| 国产综合色区在线观看| 国内精品久久久久影院 日本资源| av大全在线免费看| 日韩精品视频免费| www.com欧美| 9191国产精品| 又骚又黄的视频| 日本韩国欧美一区| 亚洲婷婷综合网| 婷婷开心久久网| 久久久.www| 亚洲人成网站影音先锋播放| 性猛交ⅹxxx富婆video| 北岛玲一区二区三区四区| 色哟哟免费视频| 精品一区二区久久| 奇米视频7777| 久久99深爱久久99精品| 无需播放器的av| 免费国产亚洲视频| 一级在线免费视频| 男女性色大片免费观看一区二区| 欧美成人黑人猛交| 久久亚洲视频| caopor在线视频| 日韩成人免费看| 国产自偷自偷免费一区| 日韩精品1区2区3区| 国产av人人夜夜澡人人爽| 久久午夜视频| 国产福利一区视频| 日韩经典一区二区| 男女污污的视频| 蜜桃视频第一区免费观看| 国产视频1区2区3区| 麻豆91精品视频| 伊人影院综合在线| 韩国三级在线一区| 老司机av网站| 国产高清精品久久久久| 欧美xxxxx精品| 91一区二区三区在线观看| 国产熟妇搡bbbb搡bbbb| 久久老女人爱爱| 夫妇露脸对白88av| 成人免费小视频| 精品无码久久久久久久| 大桥未久av一区二区三区| 天天爽夜夜爽人人爽| 精品视频999| 99精品免费观看| 精品第一国产综合精品aⅴ| 性感美女视频一二三| 国产一区二区成人| 超碰免费在线播放| 97精品视频在线观看| 日韩国产网站| 亚洲一区二区免费在线| 精品精品国产三级a∨在线| 日韩av一区二区三区在线| 婷婷丁香综合| 僵尸世界大战2 在线播放| 蜜桃久久av| 免费看的av网站| 26uuu亚洲综合色| 性少妇xx生活| 亚洲图片欧美综合| 国产日韩久久久| 欧美mv日韩mv| 蜜桃视频在线入口www| 精品国偷自产在线视频99| 国产黄色大片在线观看| 国产福利精品视频| 51精品国产| 日韩国产一区久久| 欧美三级第一页| 亚洲狼人综合干| 成人综合激情网| 国产欧美一区二区三区在线观看视频| 亚洲精品成人a在线观看| 五月天激情国产综合婷婷婷| 欧美一区二区三区在线| 青青草在线播放| 欧美人与性动交a欧美精品| 欧美日韩免费看片| www.av一区视频| 日韩系列欧美系列| 凹凸国产熟女精品视频| 国产乱子伦视频一区二区三区| 欧美激情aaa| 亚洲成人福利片| av片免费播放| 在线精品播放av| 欧美xxx网站| 国产三区二区一区久久| 91成人国产| 香港日本韩国三级网站| 91一区二区三区在线观看| 免费毛片在线播放免费| 欧美日韩mp4| 国产鲁鲁视频在线观看免费| 久久欧美在线电影| 人人九九精品视频| 一本色道久久综合亚洲精品婷婷| 蜜乳av另类精品一区二区| 水蜜桃av无码| 亚洲在线视频一区| 国产欧美久久久| 日韩在线视频中文字幕| 电影亚洲精品噜噜在线观看| 久久久一本精品99久久精品66| 亚洲午夜视频| 色欲无码人妻久久精品| 亚洲欧美日韩小说| 91精品国产色综合久久不8| 国产亚洲精品日韩| 黑人巨大亚洲一区二区久| 极品日韩久久| 99精品久久| 亚洲av无码一区二区三区网址 | 大黄网站在线观看| av观看久久| 亚洲国产精品久久久天堂| 亚洲黄色av片| 亚洲乱码国产乱码精品精的特点| 国产精品久久久久久免费| 日日骚av一区| 国产精品伊人| 亚洲图片小说在线| 精品在线观看免费| 成人涩涩小片视频日本| 69堂精品视频| 日韩av官网| 国产精品毛片一区视频| 极品少妇一区二区三区| 97精品人妻一区二区三区蜜桃| 亚洲成人一二三| 亚洲三级中文字幕| 日韩美女视频免费在线观看| 国产伦精品一区二区三区千人斩| 波多野结衣天堂| 国产精品久久久久影院亚瑟| av免费观看网址| 久久久久久91| 美女毛片一区二区三区四区最新中文字幕亚洲| 日本福利视频在线| 一区二区三区在线视频观看| 日韩精品―中文字幕| 不卡的av网站| 麻豆久久久久久久久久| 日韩伦人妻无码| 国产肉丝袜一区二区| 无码人妻精品一区二区| 色先锋资源久久综合5566| japansex久久高清精品| 91看片淫黄大片91| 99免费精品在线| 成人免费a视频| 国产一区二区三区三区在线观看| 六九午夜精品视频| 五月天激情图片| 99精品视频免费在线观看| 日韩一级在线视频| 色偷偷av一区二区三区| 亚洲一二av| 国产乱子夫妻xx黑人xyx真爽| 中文乱码免费一区二区| 精品国产亚洲一区二区麻豆| 91精品国产乱码久久久久久久久 | 激情一区二区三区| 青青国产91久久久久久| 毛片a片免费观看| 亚洲天堂男人天堂| 三级欧美日韩| 欧美精品aaaa| 亚洲一区二区三区爽爽爽爽爽| 男男激情在线| 91手机在线视频| 久久久水蜜桃av免费网站| 91 在线视频| 精品夜色国产国偷在线| 99亚洲男女激情在线观看| 日日鲁鲁鲁夜夜爽爽狠狠视频97| 亚洲欧洲日韩在线| 奇米影视888狠狠狠777不卡| 亚洲字幕在线观看| 日韩不卡在线观看日韩不卡视频|