上个星期自己感冒了、前前后后去了几趟医院,中间有时间就继续探究Tinker的热修复过程,最后用keynote给同事们做了次分享;内容较深、都是干货
-
Nuwa修复原理
先说nuwa的修复原理,我们知道classLoader的加载过程、从Elements数组中先找到的class 就先进行加载,所以我们就可以将需要修复的class放到打补丁dex中然后插入到Elements数组的前面从而实现修复;但这个过程还有一个问题,如果引用者这个类被打上CLASS_ISPREVERIFIED 标志,那么就会进行dex的校验;而被打上CLASS_ISPREVERIFIED标志的过程是因 为apk在安装时虚拟机会将dex转化成odex文件,然后才会执行;在转成odex文件过程中,会执行dvmVerifyClass 进行类的校验;校验成功会打上CLASS_ISPREVERIFIED的标志,校验规则就是一个类中直接引用到的类和clazz都在同一个dex中的话,那么这个类就会被打上CLASS_ISPREVERIFIED;所以 为了不让打上标志,在编译时往所有类的构造函数里面插入一段代码
if(ClassVerifier.PREVENT_VERIFY) {
System.out.println(AntilazyLoad.class );
}
其中AntilazyLoad类会被打包成单独的hack.dex,这样当安装apk的时候,classes.dex内的类都会引用一个在不相同dex中的AntilazyLoad类,这样就防止了类被打上CLASS_ISPREVERIFIED的标志了,只要没被打上这个标志的类都可以进行打补丁操作
具体分析过程见https://mp.weixin.qq.com/s?__biz=MzI1MTA1MzM2Nw==&mid=400118620&idx=1&sn=b4fdd5055731290eef12ad0d17f39d4a
-
tinker修复原理
nuwa因为插桩,对运行的性能有不小影响;所以tinker从另一个方向出发进行修复:dex结构,我们先看dex的结构:
详情介绍可参考:
http://blog.csdn.net/feglass/article/details/51761902
https://www.jianshu.com/p/f7f0a712ddfe
我们通过010软件看到dex 文件内容:
然后对比修复后的dex文件:
通过分析结构,我们可以找出修复包与原包的差异,记录差异位置及操作并将其打包成补丁文件下发,然后将原安装包与补丁合成修复包内容;从而达到修复的目的。
上面是其修复原理,下面我们再先了解下三种编译方式:
前端编译:javaàclass
JIT编译(just in Time):classà机器码
AOT编译(ahead of time):java/.classà机器码
详情可参考:
http://blog.csdn.net/tjiyu/article/details/53748965
安卓系统中虚拟机的发展从dalvik到art再到混合编译;其编译方式也有不少变化,所以对补丁修复也有影响
资料可参考学习:
Android运行时ART 简要介绍和学习计划
http://blog.csdn.net/luoshengyang/article/details/39256813
Android N混合编译与对热补丁影响解析
http://blog.csdn.net/offbye/article/details/52588576#reply
既然各平台的运行方式有差异,对我们的补丁也有不同的影响;那么我们的补丁合成也相应的进行了分平台合成:art平台进行差量合成、dalvik 平台进行全量合成;androidN平台进行功能退化修复;
接着我们再看tinker对资源及so库的修复
其分析可参考:
http://blog.csdn.net/sbsujjbcy/article/details/52541803? hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io
http://dev.qq.com/topic/57ad7a70eaed47bb2699e68e
-
功能对比
通过tinker修复原理的学习、有一点深刻的哲学感悟:“世界是一个整体”;那些大学学过的东西在这里串成了一个整体;