Android Studio升级到2.0之后,新增了Instant Run功能,该功能可以热替换apk中的部分代码,大幅提高测试安装的效率。

但是,由于我的项目中自定义了一些ClassLoader,当使用InstantRun时,经常出现class加载不正确的问题。分析后原因如下。

使用Instant Run编译出的apk里面会多出几个dex文件,和一个instant-run.zip,这个zip里也是一堆dex文件:

所以推测,instant Run的实现原理是:

根据代码结构,将App的源码分割成多个dex,然后使用自定义的classloader来加载他们,当然这个自定义的classloader也要继承BaseDexClassLoader,因为BaseDexClassLoader里有个DexPathList,这个所谓的List里存的是多个dex的文件信息,所以当某段代码修改时,只需编译和替换相应的dex文件即可(这同样也是MultiDex的实现原理)。

下面我们简单验证一下。

首先正常的apk运行时,其classloader打印出来是这样的:

dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.zkw.hostdemo-1/base.apk"],nativeLibraryDirectories=[/data/app/com.zkw.hostdemo-1/lib/arm, /system/lib, /vendor/lib, system/vendor/lib, system/vendor/lib/egl, system/lib/hw]]]

而使用Instant Run运行起来的apk,其classloader打印出来长这样:

com.android.tools.fd.runtime.IncrementalClassLoader$DelegateClassLoader[DexPathList[[dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-support-annotations-23.3.0_6be31c7c3de045eced09b0e58c45c46ba1a8b4da-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-slice_9-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-slice_8-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-slice_7-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-slice_6-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-slice_5-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-slice_4-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-slice_3-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-slice_2-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-slice_1-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-slice_0-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-ormlite-core-4.47_2aa30d6da8ed45bfc6255e592f80eb5f44eace4c-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-ormlite-android-4.47_a7ee90c985672a4cd4bdfca79190a330465fcdb0-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-lecore_4c1e07fda866033d90832ceae724962d4943e790-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-internal_impl-23.1.1_12c3206fb094d3315355dc809fcd39ad94f6e5e8-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-fastjson-1.1.45.android_317ce285230b187682809682934f3690b4d9580d-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-com.android.support-support-v4-23.1.1_1cfecee433501e7056d02c08b2393c569c575b33-classes.dex", dex file "/data/data/com.zkw.hostdemo/files/instant-run/dex/slice-com.android.support-multidex-1.0.1_a3117677a6ad7ee678ee3f3a4af434c4d08ee7ba-classes.dex"],nativeLibraryDirectories=[/data/app/com.zkw.hostdemo-1/lib/arm, /system/lib, /vendor/lib, system/vendor/lib, system/vendor/lib/egl, system/lib/hw]]]

很长吧,发个截图:

可以看到这个ClassLoader是:com.android.tools.fd.runtime.IncrementalClassLoader$DelegateClassLoader,DexPathList对应着instant-run.zip里的所有dex。

到这里,感觉基本符合我的猜想,但是这个IncrementalClassLoader是如何添加到设备中的,又如何在运行时起作用的,我们接着分析。

instant run运行的apk里,和class有关的就是classes.dex、classes2.dex和instant-run.zip里的dex。

通过观察命名和反编译,我发现instant-run.zip里的dex都是和我们app代码相关的,而classes.dex和classes2.dex是AndroidStudio编译时自己添加的,其中classes2.dex最重要,我们反编译看看:

终于看到了熟悉的IncrementalClassLoader,那这个classloader是怎么生效的呢,我们看看BootstrapApplication的源码(可想而知,AndroidManifest文件中的application属性也被Android Studio改了):

注意标绿的那行,继续进去看看(那行下面有个createRealApplication(),其实就是通过反射获取app自定义的Application,然后做对应的操作):

灰色的那行就是安装IncrementalClassLoader的地方,进入IncrementalClassLoader的inject()看看,

源码中可以看到,Studio其实就是利用反射,将自己的IncrementalClassLoader设置成app中默认ClassLoader的parent,这样就拦截了所有类加载的动作,从而实现了对多个dex文件的动态加载。

到此,原理分析结束。

所以如果你的app里用到了自定义的ClassLoader,请谨慎使用Instant Run!

谢谢阅读,转载请注明出处。

[原创]Android Studio的Instant Run(即时安装)原理分析和源码浅析的更多相关文章

  1. AndroidKiller报.smali文件丢失问题解决(关闭Android Studio的Instant Run)

    第一节编写一个Android程序里我们生成了一个验证激活码的apk,当我们输入的激活码正确时才能注册成功,输入错误时注册失败. 现在我们想输入错误的激活码也能注册.我们用Android反编译工具进行反 ...

  2. android studio2.0出现的gradle问题,instant Run即时运行不了.

    android studio 2.0出现的gradle问题: instant Run即时运行不了.经历了几乎9个preView版本的AS2.0,终于迎来了正式版,然而晴天我的霹雳,好不容易装好的2.0 ...

  3. Android新特性Instant Run详解

    关于 Instant Run Android Studio 2.0 中引入的 Instant Run 是 Run 和 Debug 命令的行为,可以大幅缩短应用更新的时间.尽管首次构建可能需要花费较长的 ...

  4. Android Studio和SDK下载、安装和环境变量配置

    win10下Android Studio和SDK下载.安装和环境变量配置                                                               - ...

  5. Android studio Unable to run mksdcard SDK tool

    /******************************************************************************************** * Andr ...

  6. Android Studio(一):介绍、安装、配置

    Android Studio相关博客: Android Studio(一):介绍.安装.配置 Android Studio(二):快捷键设置.插件安装 Android Studio(三):设置Andr ...

  7. Android Studio 1.0 苹果电脑安装配置

    ​ 前言 近日Google终于不负众望,发布了期待已久的Android Studio 1.0正式版.小编自己是Android开发者,之前使用过Eclipse,也试用过Android Studio 0. ...

  8. Android Studio中mac上面的安装

    Android Studio中mac上面的安装 学习了:https://blog.csdn.net/xianrenli38/article/details/79347170 http://www.an ...

  9. Android Studio 和 SDK 下载、安装和环境变量配置

    转Android Studio 和 SDK 下载.安装和环境变量配置https://blog.csdn.net/hahahhahahahha123456/article/details/8065135 ...

随机推荐

  1. 修改开机启动等待时间(for Ubuntu12.10)

    Ubuntu的开机启动等待时间默认是10s,等待时间比较长,每次启动都得按一下回车,于是就想修改一下等待时间.我们可以找到Grub的配置文件(/boot/grub/grub.cfg),在其中进行个性化 ...

  2. C#执行OracleHelper

    /// <summary> /// 执行存储过程获取带有Out的参数 /// </summary> /// <param name="cmdText" ...

  3. 真实世界:使用WCF扩展在方法调用前初始化环境

    OperationInvoker 介绍 OperationInvoker 是 WCF 运行时模型中在调用最终用户代码前的最后一个扩展点,OperationInvoker 负责最终调用 Service ...

  4. jquery 常用插件

    50款最有用的 jQuery 插件集锦<表单篇> 50款最有用的 jQuery 插件集锦<网页布局篇> 50款最有用的 jQuery 插件集锦<内容滑块篇> 50款 ...

  5. 【转】Asp.Net MVC及Web API框架配置会碰到的几个问题及解决方案

    前言 刚开始创建MVC与Web API的混合项目时,碰到好多问题,今天拿出来跟大家一起分享下.有朋友私信我问项目的分层及文件夹结构在我的第一篇博客中没说清楚,那么接下来我就准备从这些文件怎么分文件夹说 ...

  6. AngularJS快速入门指南08:表格

    ng-repeat指令非常适合用来显示表格. 在表格中显示数据 在AngularJS中显示表格非常容易: <div ng-app="myApp" ng-controller= ...

  7. paip. http 405 的解决..

    paip.  http  405 的解决.. get>>> POST 或者 syeofe.. 作者Attilax  艾龙,  EMAIL:1466519819@qq.com 来源:a ...

  8. Leetcode 219 Contains Duplicate II STL

    找出是否存在nums[i]==nums[j],使得 j - i <=k 这是map的一个应用 class Solution { public: bool containsNearbyDuplic ...

  9. 如何在安装程序中判断操作系统是否是64位 inno

    [Setup]; 开启64位模式ArchitecturesInstallIn64BitMode=x64 [Run] ;根据是否是64位进行不同的操作Filename: "..."; ...

  10. Java注释Override、Deprecated、SuppressWarnings详解

    一.什么是注释 说起注释,得先提一提什么是元数据(metadata).所谓元数据就是数据的数据.也就是说,元数据是描述数据的.就象数据表中的字段一样,每个字段描述了这个字段下的数据的含义.而J2SE5 ...