当我们在谈论multidex65535时,我们在谈论什么
本文来自网易云社区
作者:郑文
首先我们并不在讨论车牌号.本文尽量避免谈论重复的技术点,只探讨一下multidex提供给我们的技术启示。
原理
multidex技术原理可以分成两个部分:
在app启动时,通过Multidex.install api,扩展ClassLoader的dexElements数组来存储所有dex,这个流程会根据android sdk版本的不同做不同的处理,整个流程完全通过反射完成。
编译过程中的分包机制,将app中的class以某种方式将class分布在多个dex中
Multidex.install
从multidex的原理,很容易想起目前比较流行的一个代码热修复方案策略。安卓App热补丁动态修复技术介绍,qzone的技术思路在社区诞生了很多技术框架,其中知名度最高的就是Nuwa。但客观的说,nuwa这个项目是完全达不到产品release的要求。在调研完所有同技术路线开源框架后,我们决定造个能应用在线上产品的轮子。
我们的解决方案
使用Transform API进行bytecode的植入,支持高版本gradle
编译流程的优化,减少了人工干预的过程
支持补丁包的签名验证,避免被恶意hook
兼容网易安全部门的加壳方案
支持ART模式:在art模式下,应用补丁包可能导致地址错乱,解决方案是将直接引用修改class的相关类都打包进行补丁包,这是目前其他开源方案没有做的
MultiDex存在的问题
MultiDex机制的出现本身是为了避免出现app 65535问题的出现,但随着业务逻辑的增长,以及不合理的模块划分,导致main dex的方法数也超出了65535,这就导致了main dex capacity exceeded异常。
同时,Multidex的接入额外还会对app的启动性能造成影响。Multidex在install时需要加载dex,首次启动时还需要做odex的转换,而这些都是在ui主线程中完成。 根据Carlos Sessa的测试,启用multidex后,4.4或以下的设备,app的启动时间平均会增加15%的时间,更严重的情况,甚至在启动时候会出现了黑屏。
目前部分app采取的策略是,放弃掉Multidex的,而转为插件化的架构。通过将非核心模块的lazy load,来达到启动速度的优化,但我们需要明确的是,并不是所有app都似乎插件化架构,为了实现启动加速或热更新将本耦合的业务逻辑硬生生拆解才是本末倒置。
解决方案
Multidex异步化
在Android的性能优化中,最常见的思路就是异步化,减少UI线程的工作。在应用的交互层面上,app启动时,几乎所有app都会有一个SplashActivity。在界面上展示欢迎页,在后台进行初始化的业务逻辑。这就给我们一个启发,我们可以将系统的初始化逻辑,延迟到我们的业务初始化时间点上。
更加具体的方式是,我们可以将Multidex.install异步化,保证主线程的正常进行,待加载完成后通知SplashActivity跳转到真正的业务主界面。
在MultiDex加载的异步化之后,我们可以进行第二步:main dex大小的精简。
Multidex分包原理介绍
Multidex会在入口Application的attachBaseContext,加载second dex,因此multidex分包的基本原则是:保证app启动需要的class放置在main dex上。在gradle 1.5以上,multidex通过CreateManifestKeepList和MutidexTransform完成,分包过程可以分为三步:
生成manifest_keep.txt
CreateManifestKeepList会解析出AndroidManifest.xml中所有的组件类:包括Activity、Service、Receiver以及ContentProvider,这些类将会和Application入口类一起放在build/intermediates/multi-dex/{flavor}/{buildType}/manifest_keep.txt中
生成maindexlist.txt文件
MutidexTransform会查找manifest_keep.txt中所有类的直接引用类,具体的方式是遍历类的所有字段类以及方法,查看方法的参数和返回值的类型,将其放保存在maindexlist.txt
生成main dex
相关文章:
【推荐】 一份ECMAScript2015的代码规范(下)
当我们在谈论multidex65535时,我们在谈论什么的更多相关文章
- 当我们谈论CloudTable时究竟在谈论什么?
表格存储服务(CloudTable Service,简称CloudTable)是基于Apache HBase提供的分布式.可伸缩.全托管的毫秒级NoSQL数据存储服务.它提供了毫秒级的随机读写能力,适 ...
- 当我们在谈论 DevOps,我们在谈论什么?
Cloud Insight 携手 BearyChat:打造适合运维人员的团队协作工具 走过 C 轮的 OneAPM,旗下的产品已经日渐丰满,从应用性能监控的 Application Insight 到 ...
- MySQL Bug剖析之Slave节点并行复制死锁
此文已由作者温正湖授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 有天一早,DBA同学就找上来了,说有个DDB集群下的RDS实例Slave节点(从库)死锁了,请求支援.说实话 ...
- C/C++中数组与指针的关系探究
数组与指针 长期以来,在C/C++中,数组名和指向数组首元素的指针常量到底是以一种什么关系,一直困扰着很多人.很多地方,甚至是一些教科书中都在说,"数组名就是一个指向数组首元素的指针常量&q ...
- 以虎嗅网4W+文章的文本挖掘为例,展现数据分析的一整套流程
本文转自知乎 作者:苏格兰折耳喵 ----------------------------------------------------- 本文作者将结合自身经验,并以实际案例的形式进行呈现,涉及从 ...
- Facebook内部报告:争取青少年用户的鸡贼小技巧
翻译:吴祺深 欢迎访问网易云社区,了解更多网易技术产品运营经验. 去年十月,Facebook收购了TBH,最后却关闭了这款APP,不过一则内部报告透露了,通过这款流行的投票APP,这家公司学会了如何去 ...
- DevOps 工程师成长日记系列三:版本
原文地址:https://medium.com/@devfire/how-to-become-a-devops-engineer-in-six-months-or-less-part-3-versio ...
- OAuth 2.0、OIDC 原理
OAuth 目录 OAuth 什么是 OAuth? 为什么是 OAuth? SAML OAuth 和 API OAuth 主要组件 OAuth 作用域 OAuth 参与者 OAuth 令牌 OAuth ...
- [Erlang 0116] 当我们谈论Erlang Maps时,我们谈论什么 Part 1
Erlang 增加 Maps数据类型并不是很突然,因为这个提议已经进行了2~3年之久,只不过Joe Armstrong老爷子最近一篇文章Big changes to Erlang掀起不小了风 ...
随机推荐
- Spring cloud Hystrix的配置属性优先级和详解
Hystrix配置属性详解 Hystrix可以配置属性的有以下类型: Execution:控制HystrixCommand.run() 的如何执行 Fallback: 控制HystrixCommand ...
- Discuz 任务、道具、任务和验证类插件制作
一.广告类脚本位置:source/class/adv/adv_name.php语言包位置:source/language/adv/lang_name.php <?php class adv_na ...
- JVM 调优参数设置
先看Linux内存大小(假设为2G) cat /proc/meminfo |grep MemTotal 查看java初始配置 java -XX:+PrintFlagsInitial Tomcat配置 ...
- JAVA - 守护线程(Daemon Thread)
转载自:http://www.cnblogs.com/luochengor/archive/2011/08/11/2134818.html 在Java中有两类线程:用户线程 (User Thread) ...
- PHP GD库
<?php $file = '12.jpg'; //打开图片 $im = imagecreatefromjpeg($file); //设置水印字体颜色 $color = imagecoloral ...
- jQuery 复制节点的元素实现添加到购物车功能
描述: 用户点击左边div中的商品,对应商品会自动添加到右面的div中,类似电子商城中的添加到购物车功能. 主要用到了jquery中的复制节点功能,基本原理是首先获取点击的元素,然后将相应信息进行克隆 ...
- IDEA07 快捷键统计插件之Key Promoter X
1 官方介绍 该插件会统计你鼠标操作的次数,然后在一个窗口中展示出来 https://plugins.jetbrains.com/plugin/9792-key-promoter-x 2 下载.安装. ...
- 存储过程返回update结果集和insert主键
update teacher set name ='111' where id in(286,289);print @@rowcount;--或select将查出,是@@rowcount,不是@row ...
- JAVA高并发线程
一.JAVA高级并发 1.5JDK之后引入高级并发特性,大多数的特性在java.util.concurrent 包中,是专门用于多线程发编程的,充分利用了现代多处理器和多核心系统的功能以编写大规模并发 ...
- php解决时间超过2038年
问题 超过2038年的时间 php怎么处理? echo date('Y-m-d',2147483647); //date函数能处理的最大整数2147483647 ->2038-01-19 就是2 ...