本文通過(guò)學(xué)習(xí)聊聊 APK —— Dex 熱修復(fù)與 Classpath 總結(jié)
在將java文件直接運(yùn)行在JVM和Dalvik中,中講解了java程序如何在JVM和Dalvik中運(yùn)行,其中在Android部分實(shí)現(xiàn)是,先將java文件轉(zhuǎn)為dex文件,導(dǎo)入至安卓手機(jī)中,通過(guò)Dalvik對(duì)該文件編譯運(yùn)行,實(shí)現(xiàn)將java文件運(yùn)行在手機(jī)中功能。本文重點(diǎn)講解如何利用該功能實(shí)現(xiàn)簡(jiǎn)易熱修復(fù)的效果。
熱修復(fù)的根本原理是通過(guò)修改DexClassLoader 中dexPathList 的dex順序,達(dá)到熱修復(fù)的效果。
1.制作帶有bug的dex
首先創(chuàng)建一個(gè)帶有打印bug的類test.java,如下所示:
package xiaohan;
public class Test {
public void test (){
System.out.println("This a BUG!");
}
}
這里需要注意,由于此類需要在帶有main的類中引用,需要自定義一個(gè)package,否則無(wú)法正常引用該類。
創(chuàng)建一個(gè)帶有main的主類HelloWorld.java,該類中需要引用Test,通過(guò)import的形式引入。
import xiaohan.Test;
public class HelloWorld {
public static void main (String [] args){
Test test = new Test();
test.test();
}
}
由于需要加載兩個(gè)java文件,需要通過(guò)以下語(yǔ)句執(zhí)行,注意cp之后有個(gè) “.”的修飾符。
javac -cp . HelloWorld.java Test.java

將生成的兩個(gè)class文件,生成一個(gè)dex文件,這例需要注意,如果直接按照之前的語(yǔ)句:
dx --dex --output=xiaohan.dex HelloWorld.class Test.class
則會(huì)出現(xiàn)以下錯(cuò)誤:
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
原因是由于在創(chuàng)建Test.java文件時(shí),為其指定了包名為xiaohan,與HelloWorld不在同一包下,因此需要?jiǎng)?chuàng)建一個(gè)xiaohan的文件夾,將Test.class拷貝進(jìn)去,然后執(zhí)行如下語(yǔ)句:
dx --dex --output=xiaohan.dex HelloWorld.class xiaohan/Test.class
就會(huì)生成一個(gè)的xiaohan.dex文件,將其拷貝至手機(jī)后,運(yùn)行如下語(yǔ)句:
dalvikvm -cp xiaohan.dex HelloWorld
結(jié)果如下:

2. 制作補(bǔ)丁包
重新創(chuàng)建一個(gè)新的test.java文件,修改其內(nèi)容如下:
package xiaohan;
public class Test {
public void test (){
System.out.println("Fix a BUG!");
}
}
制作一個(gè)新的class文件,注意只需要制作Test.class文件,與HelloWorld.class無(wú)關(guān),制作語(yǔ)句如下,去除“.”,包含HelloWorld因?yàn)樵诰幾g時(shí)會(huì)報(bào)錯(cuò)。
javac -cp HelloWorld.java Test.java

將新制作的Test.class文件制作成功獨(dú)立的dex文件,這里命名為new.dex,通過(guò)執(zhí)行如下語(yǔ)句:
dx --dex --output=new.dex xiaohan/Test.class
該dex的是制作補(bǔ)丁包,只包含test.class文件,不包含HelloWorld.class文件。
將生成的new.dex文件,推送至手機(jī)存放HelloWorld.dex的目錄下,執(zhí)行修復(fù)后的語(yǔ)句,如下所示。
dalvikvm -cp new.dex:xiaohan.dex HelloWorld
注意,這里需要將補(bǔ)丁包放置前面,然后再添加xiaohan.dex(包含main的dex文件),否則如果先添加new.dex或者不添加,則無(wú)法到達(dá)修復(fù)效果,如下語(yǔ)句。
dalvikvm -cp xiaohan.dex:new.dex HelloWorld
