写点什么

开源 | BoostMultiDex:挽救 Android Dalvik 机型 APP 升级安装体验

  • 2020-06-01
  • 本文字数:2421 字

    阅读完需:约 8 分钟

开源 | BoostMultiDex:挽救 Android Dalvik 机型APP升级安装体验

现代 Android APP 的代码量通常都比较大,很容易就会带上多个 DEX 文件。Android 低版本的设备采用的 Java 运行环境是 Dalvik 虚拟机,如果含有多个 DEX 想要在这些设备上正常运行,就需要使用官方的 MultiDex 方案。MultiDex 需要对 APK 内的原始 DEX 文件做 ODEX 优化,所以执行时间过于漫长,这就会使得安装或者升级后首次 MultiDex 花费的时间很久。


抖音自研的 BoostMultiDex 方案,可以大幅改善原有的 MultiDex 耗时。并且,不同于目前业界所有优化方案,我们是从 Android Dalvik 虚拟机底层机制入手,从根本上解决了安装后首次执行 MultiDex 耗时过长问题。


之前已经发布过两篇文章,详细介绍了 BoostMultiDex 的实现原理:


抖音 BoostMultiDex 优化实践:Android 低版本上 APP 首次启动时间减少 80%(一)


抖音 BoostMultiDex 优化实践:Android 低版本上 APP 首次启动时间减少 80%(二)


其中也展示了这一优化带来的显著效果:


开源地址


Github 项目地址:


https://github.com/bytedance/BoostMultiDex

实际表现

我们之前的文章里面只是提到了技术分析和一些优化数据,为了让大家更加直观地感受 BoostMultiDex 带来的明显效果,这里就来看下我们项目中实际表现是怎样的,以今日头条 APP 为例,左边是 BoostMultiDex,右边是原始 MultiDex:


https://mp.weixin.qq.com/mp/readtemplate?t=pages/video_player_tmpl&auto=0&vid=wxv_1355562813275815937


可以明显看到页面打开时间的差距,左边的 BoostMultiDex 方案有非常显著的优化,界面在短暂等待后就立即展示出来了,而右边的原始 MultiDex 方案要等待半分钟左右才能展示界面。


当然,这个优化带来的实际体验提升情况,还要看结合每个 APP 自身。除了加载多 DEX 的时间,APP 启动阶段还有大量自身业务逻辑,而这块的耗时是相对固定的。这属于业务层面的启动优化问题了,应当尽量减少启动阶段执行那些不会立即使用的模块加载。 而 BoostMultiDex 的接入成本极低,能保证仅替换一行代码,就达到立竿见影的效果。

快速接入

本方案的使用和官方 MultiDex 基本上是一致的,只需两步即可接入。


首先,在 build.gradle 的 dependencies 中添加依赖:


dependencies {... ...    implementation 'com.bytedance.boost_multidex:boost_multidex:${ARTIFACT_VERSION}'}
复制代码


然后,与官方 MultiDex 类似,在 Application.attachBaseContext 的最前面进行初始化:


public class YourApplication extends Application {
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base);
BoostMultiDex.install(base);
... ... }
复制代码


这样就完成了所有工作了。立马编译运行,看看是不是 APP 首次冷启动变得健步如飞?

一些补充

之前的两篇文章中已经对 BoostMultiDex 方案的技术实现细节有详细叙述,主要涵盖了以下几个


技术要点:


  1. 利用系统隐藏函数,直接加载原始 DEX 字节码,避免 ODEX 耗时

  2. 多级加载,在 DEX 字节码、DEX 文件、ODEX 文件中选取最合适的产物启动 APP

  3. 单独进程做 OPT,并实现合理的中断及恢复机制


此外,这里再补充一些说明。

主 DEX 相关

首先,和 MultiDex 一样,BoostMultiDex 的所有类都是需要打入主 DEX 里面的,默认情况下,由于 Application 内有直接引用 BoostMuliDex,Gradle 就会自己帮我们自动打入主 DEX。但如果由于某些罕见的异常情况没有打入,我们就需要自己额外做这个处理,强制把com.bytedance.boost_multidex包中的所有类打入到主 DEX 里。

对于 ODEX 优化进程的处理

ODEX 优化进程是在名为:boost_multidex的进程中的,他会开启一个OptimizeService后台服务做优化,当然,所有进程都会走到Application里,Application里包含了很多其他进程共有逻辑,对于 ODEX 优化进程而言,这些逻辑是不需要的,因此,我们提供了一个BoostMultiDex.isOptimizeProcess方法,便于使用者自行判断,直接跳过这些无关业务逻辑。由于整个 BoostMultiDex 都在主 DEX 中,因此对于 ODEX 优化进程,BoostMultiDex.install也是不需要的。当然不做这个判断也关系不大,只是会额外执行一些无用代码,有些许效率损失。

Android 4.4 的 ART 机型

Android 4.4 机型同时集成了 Dalvik 和 ART 两套虚拟机,一般厂商的默认出厂机型都是采用 Dalvik 的。由于本方案只针对 Android Dalvik 机型有优化,对 ART 是没有效果的,因此,如果遇到某个机型优化效果差异不大,可以先看下是什么机型,并从输出日志可以看出是什么原因没有走到优化逻辑。

部分 Dalvik 内部数据结构有偏移的机型

我们的方案中涉及到对 Dalvik 虚拟机内部DvmDex结构体做设置,而如果厂商对这些结构做了特殊修改,就会导致设置到错误的偏移。这种情况目前看来还是极少的,仅在我们在线上大面积灰度过程中发现了一些 HTC 机型有修改这个结构,对此我们已经做了修正。这里也提前说明,避免大家在看到这块代码的时候遇到困惑。

最后

当然,技术上说的再多,不如看实际收益。目前,BoostMultiDex 已经在抖音亿级全球用户上验证通过,可以说涵盖了各种复杂情况的 Android 机型,目前业界其他大型 APP 都很难涉及到如此广泛的规模。由此,我们也解决了各种奇怪的兼容性问题,最大程度上确保了技术方案的稳定性。


对于项目的开源代码,我们保证, 和抖音自身使用的代码完全一致 ,直接开箱即用,避免大家接入后还要自己踩一遍我们曾经遇到的坑。如果在实际使用过程中如果遇到什么问题,我们也希望大家及时提出,一起贡献代码,共同将 BoostMultiDex 打造得更加稳健高效。


目前, 抖音 Android 基础技术团队仍在上海、北京、杭州、深圳大力招人 ,如果你也同样对技术充满热情,同样追求极致优化,想要与我们共同建设亿级用户全球化 APP,那就欢迎进入字节跳动招聘官网查询抖音 Android 相关职位,也可以联系 xiaolin.gan@bytedance.com 咨询相关信息或者直接发送简历内推!


本文转载自公众号字节跳动技术团队(ID:toutiaotechblog)。


原文链接


https://mp.weixin.qq.com/s/0gtkc7IQdhKjFxrHCuNZwQ


2020-06-01 10:061567

评论

发布
暂无评论
发现更多内容

通过Postman和coding.net发布API

太极程序员

Postman API

DolphinDB与MongoDB在时序数据上的对比测试

DolphinDB

mongodb 分布式系统 时序数据库 DolphinDB 数据库开发

LeetCode题解:127. 单词接龙,BFS+统计单词变化次数,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

智慧警务可视化平台开发,重点人员管控系统搭建

t13823115967

智慧公安 智慧警务系统开发

硬肝到秃头!Alibaba强推并发编程笔记我跪了,真的学到好多东西!

Java架构追梦

Java 学习 架构 面试 并发编程

硬核编程:30天=一个网站+一份周刊

老魚

程序员 建站 web全栈

SPI 在 Dubbo中 的应用

vivo互联网技术

Java jdk dubbo spi

如何快速打造一款钉钉 Go sdk

Ceelog

钉钉 企业微信 Go 语言

盘点2020 | 30岁了,我终于入门编程了

盘点2020

腾讯高工强烈推荐的“Netty速成手册”原理+应用+调优,带你将知识点一网打尽

比伯

Java 编程 程序员 架构 Netty

从源码的角度搞懂 Java 动态代理!

Java架构师迁哥

码了2000多行代码就是为了讲清楚TLS握手流程(续)

Gopher指北

https Go 语言

答了Mybatis这个问题后,面试官叫我回去等通知……

田维常

mybatis

产品策略闭环是个什么环?

万事ONES

项目管理 团队协作 需求管理 需求分析 产品策略

IDEA 文档插件 DocView 版本更新:修改 UI 并支持 IDEA 2020.3 !

程序员小航

idea插件 IntelliJ IDEA 文档生成

从 JMM 透析 volatile 与 synchronized 原理

码哥字节

volatile JVM JMM Java 25 周年 synchronized

解析字节算法面试真题,深入探究ArrayList应用原理

小Q

Java 学习 编程 架构 面试

将原则纳入到架构的生命中

soolaugust

架构 思考 设计

DeFi(去)中心化DAPP系统软件开发

系统开发

盘点2020 | 疫情下的思考和学习

soolaugust

盘点2020

《大数据算法》.pdf

田维常

算法

什么是全场景AI计算框架MindSpore?

华为云开发者联盟

人工智能 AI mindspore

为了SpringBoot提交Tomcat执行,我总结了这么多

小Q

tomcat 学习 面试 微服务 springboot

Canvas入门实战之用javascript面向对象实现一个图形验证码

徐小夕

Java 大前端 canvas

Prometheus TSDB(Part 2):预写日志(WAL)和检查点

Grafana 爱好者

云原生 Prometheus tsdb 可观察性

EZYTRX波场智能合约APP系统软件开发

系统开发

智慧城市建设,社区智能化系统搭建解决方案

t13823115967

智慧城市 平安小区

dubbogo 3.0:牵手 gRPC 走向云原生时代

阿里巴巴云原生

gRPC 云原生 中间件 dubbo-go Go 语言

一文带你彻底了解大数据处理引擎Flink内存管理

华为云开发者联盟

大数据 数据 处理

【经验分享】RTC技术系列之音频编解码

Hanson

面试被问高并发一脸懵?那是你没看过我整理得高并发回答模板

小Q

Java 学习 面试 高并发 性能调优

开源 | BoostMultiDex:挽救 Android Dalvik 机型APP升级安装体验_开源_字节跳动技术团队_InfoQ精选文章