热修复
原理
安卓在加载class时会通过双亲委托机制去加载一个类,先让父类去加载,如果找不到再让子类去加载某个类。
通过查看ClassLoader源码发现findClass方法是由每个子类自己实现的,比如BootClassLoader或者BaseDexClassLoader。而PathClassLoader是继承自BaseDexClassLoader的,它的findClass也是在BaseDexClassLoader里面实现的。
BaseDexClassLoader的findClass里面使用了另一个对象DexPathList去查找对应的class,这是安卓里面特有的实现。在DexPathList对象里面有一个属性dexElements,dexElements是用于存放加载好了的dex数组的,查找class是从这个dexElements数组里面去找的。
dexElements里面存放的是Element对象,findClass最终会交给Element去实现,Element又会交给Element里面的一个属性DexFile去实现。我看了下,最终是用native实现的。
回到上面的第3步中的DexPathList对象从dexElements数组里面查找class,从数组的前面往后找,找到了就返回结果,不再继续查找。
所以当我们把修复好bug了的class,搞成dex,然后通过反射等技术放到dexElements的最前面,这样系统在通过PathClassLoader找到class时,就能先找到我们放置的修复好bug的class,然后就不会再往后找了,相当于实现了热修复。这样有bug的class就不会被用了。应了一句古话,近水楼台先得月。
第6点中的反射,流程是:获取到PathClassLoader,然后反射获取到父类中的DexPathList对象,然后再反射到DexPathList对象中的dexElements数组。然后将补丁(dex)转为Element对象,插入到dexElements数组的前面(先复制出来,再合并,再通过反射放回去)。
一句话总结。将修复好的类放在dexElements的最前面,这样在加载类的时候就会被优先加载到而达到修复的目的。
最后更新于
这有帮助吗?