Dex多分包技术和热修复
来源:互联网 发布:全国教师网络研修平台 编辑:程序博客网 时间:2024/06/09 19:00
1.什么是dex多分包?
Android打包工具(aapt)将DEX文件,资源文件及AndroidManifest.xml文件(二进制格式)组合成一个应用程序包(APK),每个APK解压后都有至少一个classes.dex文件或者多个dex文件
2.dex多分包的应用场景
解决方法数越界,在Android中单个Dex(Java编译后的文件)文件所能包含的最大方法数为65536,这包含Android FrameWork、依赖的Jar包,以及应用本身的代码中所有的方法。为什么是65536呢?因为Android系统中,一个Dex文件中存储方法id用的是short类型数据,所以导致你的dex中方法不能超过65536。
实现热修复
3.ant的打包构建过程
- aapt对资源文件的映射生成R文件
- javac进行编译
- 如果有混淆则进行混淆
- 生成dex文件
- aapt打包
- 签名
- 生成APK
关于ant
- ant是阿帕奇公司的基于任务和选择任务的脚本
- ant脚本文件build.xml(eclipse)或者build.gridle(AS)
修改打包策略产生多个dex文件代码如下
<!-- 将.class文件转化成.dex文件 --> <target <!-- 指定一个任务 --> name="dex" depends="compile" > <echo message="dex..." /> <exec <!-- 执行任务 --> executable="${dx}" <!-- 执行任务 --> failonerror="true" > <arg value="--dex" /> <arg value="--multi-dex" /><!-- 多分包命令 --> <arg value="--set-max-idx-number=10000" /><!-- 指定单个dex中的方法数 --> <arg value="--main-dex-list" /> <arg value="${basedir}/main_dex_rule.txt" /><!-- 放到主dex包里面的class文件 一般放必备的一些文件,且保证绝对没有bug --> <arg value="--minimal-main-dex" /> <arg value="--output=${bin}" /> <!-- 输出位置 --> <arg value="${bin}" /><!-- 把bin下所有class打包 --> <arg value="${libs}" /><!-- 把libs下所有jar打包 --> </exec> </target>
ant其他部分标签对含义
<target name = "-code-gen"><!--在R文件资源文件进行打包生成映射文件--><target name = "-dex"><!--进行dex打包--><property><!--声明变量--><condition><!--条件--><istrue><!--条件语句 如果为true--><buildconfig><!--编译生成BuildConfig.java--><depend><!--有这个标签的标示先执行depend里面的语句才执行当前语句--><echo><!--打印--><!--所有标签基本可以按照字面意思理解-->
将主包classes.dex添加到未签名的apk中去
<!-- 根据classes.dex文件和resources.ap_生成未签名的apk包 --> <target name="package" depends="package-res-and-assets" > <echo message="package..." /> <exec executable="${apkbuilder}" failonerror="true" > <arg value="${unsigned-package}" /><!-- 输出 --> <arg value="-u" /><!-- u指创建未签名的包 --> <arg value="-z" /><!-- 资源压缩包 --> <arg value="${resources-package}" /> <arg value="-f" /><!-- dex文件 --> <arg value="${bin}/classes.dex" /> <arg value="-rf" /> <arg value="${src}" /> <arg value="-rj" /> <arg value="${libs}" /> <arg value="-nf" /> <arg value="${libs}" /> </exec> </target>
热修复
基于多分包的热修复原理就是资源替换,试用新的dex文件替换有问题的dex,但是android dex拆包方案中的类是没有重复的,如果classes.dex和classes1.dex中有重复的类,当用到这个重复的类的时候,系统会选择哪个类进行加载呢?先看看源码
public Class findClass(String name, List<Throwable> suppressed) { for (Element element : dexElements) { DexFile dex = element.dexFile; if (dex != null) { Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed); if (clazz != null) { return clazz; } } } if (dexElementsSuppressedExceptions != null) { suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions)); } return null;}
每个element对应的就是dex文件,所以加载class就是从一个个dex文件中找到对应的code。but,可以发现,一旦找到成功了以后,就直接return。
也就是说如果2个dex含有相同的class,会先返回前面那个。
so 我们的解决方案来了,使用一个新的dex,让他在element文件表的最前面,这样我们修改的class文件就会被首先加载进来。
理论上,如果在不同的dex中有相同的类存在,那么会优先选择排在前面的dex文件的类,如下图:
在此基础上,我们构想了热补丁的方案,把有问题的类打包到一个dex(patch.dex)中去,然后把这个dex插入到Elements的最前面,如下图:
好,该方案基于第二个拆分dex的方案,方案实现如果懂拆分dex的原理的话,大家应该很快就会实现该方案,如果没有拆分dex的项目的话,可以参考一下谷歌的multidex方案实现。然后在插入数组的时候,把补丁包插入到最前面去。
But 我们发现在插入patch.dex后,会报错,原因是CLASS_ISPREVERIFIED。这是个什么东东?
在类的方法中直接引用的类,如果在同一dex中,就会被打上CLASS_ISPREVERIFIED这个标志。
我们单独给一个AntilazyLoad类打包成hack.dex 这样每个class里面都调用。我们在构造函数里面添加:
public class A{ public A() { system.println(AntilazyLoad.class); }}
这样A就引用了不在一个dex里面的class,从而不会被打上CLASS_ISPREVERIFIED的代码。进而不会出现问题。
参考:安卓App热补丁动态修复技术介绍
http://blog.csdn.net/mynameishuangshuai/article/details/52703029
- Dex多分包技术和热修复
- Android热补丁动态修复技术(一)dex分包原理
- Android热修复之dex多分包架构设计
- Android热补丁动态修复技术(一):从Dex分包原理到热补丁
- Android热补丁动态修复技术(一):从Dex分包原理到热补丁
- Android热补丁动态修复技术(一):从Dex分包原理到热补丁
- Android热补丁动态修复技术(一):从Dex分包原理到热补丁
- 基于Dex分包方案---热修复、热更新、插件化
- Android dex分包方案以及热补丁修复
- Android Dex 分包+热修复(QQ空间技术方案)
- Android热修复+dex分包+相关知识总结
- Android dex分包技术
- 关于 Android中的插件化开发,dex分包,热修复(Tinker)的思考(一)
- 关于 Android中的插件化开发,dex分包,热修复(Tinker)的思考(二)
- android dex热修复
- 替换dex实现热修复
- Android dex分包方案 (多dex)
- Android dex分包方案 (多dex)
- _variant_t与其他数据类型的转换
- eclipse新建server时server name为灰色的解决办法
- sklearn中常用的数据预处理方法
- SAP HANA的procedures报Numeric overflow error
- 全面理解Unity加载和内存管理
- Dex多分包技术和热修复
- github下载项目导入
- htons(), ntohl(), ntohs(),htons() 详解
- MyEclipse+Tomcat+MAVEN+SVN项目完整环境搭建
- docker swarm在阿里云主机上single node部署沙箱环境
- PAT A1109. Group Photo (25)
- i++是否是原子操作?
- 使用jaxws建立webservice客户端并实现soap消息的handler验证示例
- java this 关键字