天天看點

Android的dex熱修複的實作基本原理

本文通過學習聊聊 APK —— Dex 熱修複與 Classpath 總結

在将java檔案直接運作在JVM和Dalvik中,中講解了java程式如何在JVM和Dalvik中運作,其中在Android部分實作是,先将java檔案轉為dex檔案,導入至安卓手機中,通過Dalvik對該檔案編譯運作,實作将java檔案運作在手機中功能。本文重點講解如何利用該功能實作簡易熱修複的效果。

熱修複的根本原理是通過修改DexClassLoader 中dexPathList 的dex順序,達到熱修複的效果。

1.制作帶有bug的dex

首先建立一個帶有列印bug的類test.java,如下所示:

package xiaohan;
public class Test {
	public  void test (){
		System.out.println("This a BUG!");
	}
}
           

這裡需要注意,由于此類需要在帶有main的類中引用,需要自定義一個package,否則無法正常引用該類。

建立一個帶有main的主類HelloWorld.java,該類中需要引用Test,通過import的形式引入。

import  xiaohan.Test;
public class HelloWorld {
	public static void main (String [] args){
		Test test = new Test();
		test.test();
	}
}
           

由于需要加載兩個java檔案,需要通過以下語句執行,注意cp之後有個 “.”的修飾符。

javac -cp . HelloWorld.java Test.java
           
Android的dex熱修複的實作基本原理

将生成的兩個class檔案,生成一個dex檔案,這例需要注意,如果直接按照之前的語句:

dx --dex --output=xiaohan.dex HelloWorld.class Test.class
           

則會出現以下錯誤:

E:\ProgramFiles\Android\build-tools\28.0.3>dx --dex --output=xiaohan.dex HelloWorld.class Test.class

PARSE ERROR:
class name (xiaohan/Test) does not match path (Test.class)
...while parsing Test.class
1 error; aborting
           

原因是由于在建立Test.java檔案時,為其指定了包名為xiaohan,與HelloWorld不在同一包下,是以需要建立一個xiaohan的檔案夾,将Test.class拷貝進去,然後執行如下語句:

dx --dex --output=xiaohan.dex HelloWorld.class xiaohan/Test.class
           

就會生成一個的xiaohan.dex檔案,将其拷貝至手機後,運作如下語句:

dalvikvm -cp xiaohan.dex HelloWorld
           

結果如下:

Android的dex熱修複的實作基本原理

2. 制作更新檔包

重新建立一個新的test.java檔案,修改其内容如下:

package xiaohan;
public class Test {
	public  void test (){
		System.out.println("Fix a BUG!");
	}
}
           

制作一個新的class檔案,注意隻需要制作Test.class檔案,與HelloWorld.class無關,制作語句如下,去除“.”,包含HelloWorld因為在編譯時會報錯。

javac -cp HelloWorld.java Test.java
           
Android的dex熱修複的實作基本原理

将新制作的Test.class檔案制作成功獨立的dex檔案,這裡命名為new.dex,通過執行如下語句:

dx --dex --output=new.dex  xiaohan/Test.class
           

該dex的是制作更新檔包,隻包含test.class檔案,不包含HelloWorld.class檔案。

将生成的new.dex檔案,推送至手機存放HelloWorld.dex的目錄下,執行修複後的語句,如下所示。

dalvikvm -cp new.dex:xiaohan.dex  HelloWorld
           

注意,這裡需要将更新檔包放置前面,然後再添加xiaohan.dex(包含main的dex檔案),否則如果先添加new.dex或者不添加,則無法到達修複效果,如下語句。

dalvikvm -cp xiaohan.dex:new.dex  HelloWorld
           
Android的dex熱修複的實作基本原理

以上隻是簡單的示範在Dalvik虛拟機中,通過修改DexClassLoader 中dexPathList 的dex加載順序,實作修複的效果,實際使用中,一般我們的APP是安裝在data/data/包名/ 目錄下, 如果需要熱修複檔案,在制作好更新檔檔案(更新檔.dex檔案)後推送至應用端,在應用使用時,判斷是否有該更新檔檔案,再通過反射形式,修改dexPathList中更新檔包的順序,實作APP熱修複的效果。可參考Android學習——手把手教你實作Android熱修複