Instant Run实现原理

16 篇文章 0 订阅
       截止今天,Android Studio 2.1.1  版本都发布了,一直很想去研究一下AS2.0大版本中最重要特性Instant Run的原理。Instant Run实际上就是一个热补丁,看了看网上一些文章,对代码修复的这一部分大概了解如下:

Instant Run

google官方关于Instant Run特性的介绍在这里:点击打开链接,按其所述,运行FloatingActionButtonBasic样例,实验Instant Run。
但是,修改方法竟然不用重启Activity,这是怎么做到的?
阅读关于几个热补丁思路的介绍,你会发现andfix和dexposed采用jni hook方法,不用重启就能修复,而Nuwa的ClassLoader思路因为类被虚拟机加载后,不会重新加载,所以需要重启。Instant Run是怎么实现不重启加载的呢,难道也是jni hook?




实现原理

和nuwa类似,一个插件一个库,Instant Run用的是gradle plugin 2.0.0-alpha1和instant-run.jar。

gradle plugin 2.0.0-alpha1

gradle plugin 2.0.0-alpha1主要有两个作用:


1.第一次运行,应用transform API修改字节码。
输出目录为Application/build/intermediates/transforms/instantRun/debug/folders/1。
    (1)给所有的类添加$change字段
       $change为IncrementalChange类型,IncrementalChange是个接口。
    (2)修改类的全部方法

       新的逻辑是:如果$change不为空,去调用$change的access$dispatch方法,参数为方法签名字符串和方法参数数组,否则调用原逻辑。


2.后续运行,dx补丁类,生成补丁dex。
输出目录为Application/build/intermediates/transforms/instantRun/debug/folders/4000。
     (1)被修改类对应的补丁类
        补丁类,并不是你修改后的类,而是由gradle plugin自动生成,实现了IncrementalChange接口的类。
        该类类名在原名后面添加$override,复制修改后类的大部分方法,实现IncrementalChange 接口的access$dispatch方法,该方法会根据传递过来的方法签名,调用本类的同名方法。
        只要把原类的$change字段设置为该类,那就会调用该类的access$dispatch方法,就会使用修改后的方法了。
     (2)被修改类的记录类
         AppPatchesLoaderImpl记录了所有被修改的类,也会被打进补丁dex。


instant-run.jar
instant-run.jar的路径为Application/build/intermediates/incremental-runtime-classes/debug/instant-run.jar。
instant-run.jar是gradle plugin帮我们自动打到dex中去的,省去了compile dependency这一步。它的主要作用有两个:
(1)设置原类的$change字段为补丁类
需要对被修改的类设置$change字段,那怎么知道哪些类被修改了?
AppPatchesLoaderImpl类不但记录了全部被修改的类,还提供load方法支持设置被修改原类$change字段,当收到补丁通知时,只需新建一个DexClassLoader,去反射加载补丁dex中的AppPatchesLoaderImpl类,调用load方法即可,load方法中会去加载全部补丁类,并赋值给对应原类的$change。
(2)重启加载补丁类
重启后怎么办?原来的补丁文件需要加载进来。
IncrementalClassLoader会在Application中去加载该应用cache目录中的补丁dex,把它设置为默认PathClassLoader的parent,由于ClassLoader采用双亲委托模型,会先去parent查找类,所以就可以加载补丁类了。



总结

       google的介绍中,也提到了Instant Run的一些局限之处,比如变量、添加删除方法等,当然这一切都会持续优化,gradle plugin 2.0也还仅仅是个alpha版本而已。
       Instant Run的实现思路蛮笨的,几乎所有的方法都修改逻辑,但不用重启这一点很赞,用这个思路可以搞一个热修复库了,有官方背景的库。
        本文主要是探究Instant Run处理代码变化的思路,对资源变化没有分析,对于一些细节比如server实现、socket传输、application替换、updateMode处理亦未提及。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值