卷起来!抖音Android包体积优化探索( 八 )


我们使用前文的 case 来说明如下:
protected void onCreate(android.os.Bundle);Code:0: aload_01: aload_12: invokespecial #2// Method android/support/v7/app/AppCompatActivity.onCreate:(Landroid/os/Bundle;)V5: aload_0// 判断是R.class的Field调用,使用ldc替换6: getstatic#3// Field com/bytedance/android/R$layout.activity_main:I6: ldc#4// int 21312962858: invokevirtual #5// Method setContentView:(I)V11: return实际上,我们并不是所有 id 都能内联,如果我们运行时通过反射 R.class 来获取某些指定名字的资源时,如果我们将其内联了,会导致运行时找不到 id 的异常 。为了防止这种情况的发生,我们可以在方案中增加一个白名单的概念,在白名单中的域将不会被内联,对应的,方案中的步骤 2,需要修改为

  • 如果该getstatic指令的目标 Class name 的为**.R 或者**.R$*形式的 Class
a.如果getstatic指令的目标 Field 在白名单中,则跳过;
b.如果getstatic指令的目标 Field 为public static int类型,则使用ldc指令将getstatic替换,直接将 Field 的实际值导入;
c.如果getstatic指令的目标 Field 为public static int[]类型,则使用newarray指令将getstatic替换,将<clinit>中 Field 的数组赋值导入 。
抖音上线此优化后减少包体积约 30.5M 。抖音能产生这么大的收益是因为抖音的 R 十分巨大,包含的 field 非常多,同时由于单个 DEX 能定义的 field 最多为 65536 个,如果不做精简则会导致 DEX 数量的剧增,从而出现 DEX 总体积暴涨的情况 。
小结今天我们介绍的这些优化可以大幅减少 DEX 包体积,很大地促进抖音的用户增长,同时也可以优化启动时虚拟机对 DEX 加载耗时 。不过这些只是抖音在字节码方面所做冰山一角,本文介绍的所有方案的实现代码,都在我们之前开源的字节码修改工具 ByteX 里:
  • https://github.com/bytedance/ByteX
当然,DEX 相关的优化还有很多 。比如我们对 Kotlin 的代码生成也进行了优化,在 Kotlin 流行的今天,也拿到了较大的收益;同时对于 DEX 本身格式和内容的优化,在抖音也落地了很多技术含量较高的方案 。这里受限于篇幅就不再详述 。
在本系列后续的文章中,我们还将继续从 DEX、资源、SO、业务治理几个大方面深入讲解抖音上我们包体积相关的技术探索,尽情期待 。
最后在这里就还分享一份由大佬亲自收录整理的学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料
这些都是我现在闲暇时还会反复翻阅的精品资料 。里面对近几年的大厂面试高频知识点都有详细的讲解 。相信可以有效地帮助大家掌握知识、理解原理,帮助大家在未来取得一份不错的答卷 。
当然,你也可以拿去查漏补缺,提升自身的竞争力 。
真心希望可以帮助到大家,Android路漫漫,共勉!

【卷起来!抖音Android包体积优化探索】


推荐阅读