【腾讯内部干货分享】分析Dalvik字节码进行减包优化
来源:互联网 发布:金山软件资产 编辑:程序博客网 时间:2024/05/16 11:11
Android结合版最近几个版本在包大小配额上超标了,先后采用了包括图片压缩,功能H5,无用代码移除等手段减包,还是有着很大的减包压力。组内希望我能从代码的角度减少一些包大小,感觉有点压力山大。经过一段时间对手q安装包反编译后的Dalvik字节码的分析,发现通过调整Java代码可以减少编译后的Dalvik字节码,从而减少包大小。在这方面我做了许多的尝试,有成功有失败,拿出来给大家分享分享,多拍砖多交流。
优化思路
通过dexdump反编译apk中的dex,得到对应Dalvik字节码,找到寻找冗余的字节码,尝试去除或替换冗余的字节码
目前主要是替换或去除原有的java代码,减少对应的Dalvik指令,从而减少安装包大小。
现在主要是从Dalvik字节码分析来调整Java代码,之后希望能够通过ASM等框架直接调整字节码减少现在的包大小。
优化效果
去除初始化赋值方案 ————减少整个手q的发布包大小80k左右。
插桩函数优化———减少整个手q的发布包大小2k左右。
其它尝试方案,包括字符串拼接、移除interface很多空方法等,因为效果比较小、难以统一修改等问题,只是列举下分析结果,大家如果项目中出现的量比较多也是可以尝试去优化的。
优化方案如下:
1、去除初始化赋值冗余
1.1、问题分析:
静态变量为类的所有对象共享,在类加载的准备阶段就会初始设置为系统零值(如下图),比如String被设置初始值为null,而在类中存在
这样的赋值行为会在之后的<cinit>()类构造器方法中执行,重复设置String A为null,增加了对应的<cinit>()方法的Dalvik指令,没有必要,可以干掉。
成员变量在对象创建内存分配完成后,对应的内存空间会被初始设置为系统零值(和静态变量一样),比如int类型被设置为0,而在类中存在
public int B=0;
这样的赋值行为会在之后的<init>()对象构造方法中执行,重复设置int B为0,增加了对应的<init>方法中的Dalvik指令,没有必要,可以干掉。
对于初始化赋值为系统分配默认零值的静态变量和成员变量,去掉初始化赋值,直接使用系统赋的系统零值,可以减少<cinit>和<init>中的Dalvik指令,从而减少包大小,而且可以提高类加载和对象创建的效率。1.2、优化要点
注意对于static final的变量必须赋初值;
interface的变量都是static final类型的;
注意只有赋值为系统赋予的零值的静态变量和成员变量才能按照这种方式优化,其它比如局部变量的改动会导致编译不通过等问题。
1.3、冗余示例:
优化前:
对应字节码:优化后:对应字节码:
减少了两行Dalvik指令的执行,最后分析结果平均优化一处可以减少安装包8个字节左右。1.4、优化结果:
目前在手Q6.3.0分支上利用自行写的过滤脚本(可以私下找我要对应的优化脚本用于对应的工程)可以看到优化的效果,如果对整个手q执行这个方案,预计能够优化80k左右,修改了4677个文件,修改了17164处冗余。
2、调整插桩对应的代码
Qzone补丁包引入了插桩这一步,需要在所有qzone类的构造函数中加入对mqq.app.MobileQQ类的引用。
优化的方案是将插桩插入到对象构造函数中的语句由
3、字符串拼接
下面是我针对String拼接的特殊情况“变量+”””和“””+变量”的不同形式举例分析Dalvik字节码。
字节码从示例中可以看出各类字符串拼接方式的优劣,如果用String.valueOf()绝对是最优方案。只是通过对“变量+”””和“””+变量”的形式在手q整个项目调整以后大概能够优化6k左右,如果只是优化qzone部分,效果比较微小,脚本方面不太好过滤对应情况,暂时没有加入,只是做了下试验。
PS:其实“String +”一般来说比StringBuffer的拼接更费字节码,这个部分可以自行验证,前提是a+b+…的形式中首位a这个为变量,而不是常量,如果a是常量,则实际上和StringBuffer等同,这也是个优化点,具体可以参考文章 从字节码视角看java字符串的拼接 。
4、调整interface到class,减少实现接口造成的空方法
很多代码中实现接口时有很多的空方法,并没有作用但还是会占用字节码,希望能够通过调整对应的interface为class,去除冗余的空方法,减少字节码,从而减少包大小。
示例如下:
这些减包思路希望能够给一起在减包路上踩坑的朋友们一些帮助吧
- 【腾讯内部干货分享】分析Dalvik字节码进行减包优化
- 【腾讯内部干货分享】分析Dalvik字节码进行减包优化
- 分析Dalvik字节码进行减包优化
- 分析Dalvik字节码进行减包优化
- 分析Dalvik字节码进行减包优化
- 【腾讯Bugly干货分享】Android减包 - 减少APK大小
- 【腾讯Bugly干货分享】React移动web极致优化
- 【腾讯Bugly干货分享】微信读书iOS性能优化
- 【腾讯Bugly干货分享】跨平台 ListView 性能优化
- 【腾讯Bugly干货分享】Android内存优化总结&实践
- 【腾讯优测干货分享】Android 内存泄漏分析心得
- 【腾讯Bugly干货分享】腾讯验证码的十二年
- 【分析】dalvik虚拟机解释执行字节码
- 【腾讯内部工具分享】U3D资源优化工具
- 【腾讯Bugly干货分享】微信iOS SQLite源码优化实践分享实录
- 【腾讯内部工具分享】内存泄漏分析工具tMemoryMonitor
- dalvik字节码问答
- Dalvik字节码
- ArcGIS Online试用 (1)
- retrofit 2.0 +RxAndroid 使用中遇到异常 【abstract method not implemented】
- 飛飛(七十九)(补)阅读程序
- 【Rails】inverse_of在has_many和belongs_to中的用法
- Java算法<1> ----持续更新中
- 【腾讯内部干货分享】分析Dalvik字节码进行减包优化
- iOS 蓝牙开发 UUID不能使用 isConnected不能使用的问题解决
- C# 其他
- Ubuntu 修改apt源
- linux ssh key登陆
- WPF中ListBox相应鼠标滚动上下翻
- Maven install报错:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
- LocalActivityManager详解
- android4.0.3 修改启动动画和开机声音