Proguard那些事儿

提到Proguard,做Android的小伙伴想必是耳熟能详的,它虽然不是由Google开发维护的,Google却将其内置在了Android开发的SDK包中,在编译过程中起到了压缩、优化、混淆Android代码的作用,可以说是Android开发必不可少的一个工具。

Proguard做了什么

如下图所示,在Android应用源码的编译过程中,Proguard将Java bytecode转化为了Optimized Java bytecode,也就是说,Proguard起到了优化Java字节码的作用 。
在这里插入图片描述
Proguard优化Java字节码的过程可以分为这四个步骤:shrink(压缩)optimize(优化)obfuscate(混淆)preverify(预校验),如下图所示。
在这里插入图片描述

  • Shrink(压缩)
    • 根据设置的EntryPoint(入口点),遍历每个Java字节码文件,确定哪些类及类成员会被程序使用到,不会被使用的则直接丢弃。
    • EntryPoint(入口点)是Proguard中非常关键的一个概念,它定义了Proguard整个优化流程的入口,通常是由-keep系列的配置来指定的,Shrink、Optimize、obfuscate操作都与EntryPoint紧密关联。
    • Proguard只会丢弃不被使用的Java字节码,开发者通常还会搭配Android Gradle插件提供的shrinkResources功能来对不被使用的资源文件进行丢弃。
  • Optimize(优化)
    • Optimize时深入到Java字节码命令的层次进行优化。
    • class维度的优化,必要时增加final标记、做枚举类拆箱(转为整数常量)、做类合并。
    • field维度的优化,必要时增加private标记、移除write-only字段、方法中直接传递字段值。
    • method维度的优化,必要时增加privatestaticfinal标记、去除synchronized标记、移除没用到的参数、直接传递参数的值而不是引用、直接返回结果值而不是引用、将方法(较短的方法、或调用次数少的方法)内联到调用方中、尾部递归简化。
    • code维度的优化,必要时合并不同分支下相同的代码块,使用窥孔优化对变量、属性的存储加载、算术指令、类型转换、分支指令、常量字符、对象实例化进行优化。基于控制流和数据流分析,移除无效的代码、空捕捉的异常、内存占用等等。
  • Obfuscator(混淆)
    • Obfuscator时会对非EntryPoint的类、类成员做重命名,默认情况下它们会被命名为简短无意义的单个或多个的英文字母。
  • Preverify(预校验)
    • 对于Android开发场景,该步骤可以直接跳过。

Proguard与R8

R8的出现

2019年Google在发布的Android Gradle插件3.3.0版本中,提到了可以替代Proguard进行代码压缩和混淆的新工具R8,开发者可以通过在grale.properties文件中添加以下配置启用R8。

android.enableR8 = true

如下图所示,在使用R8时,Android代码的编译步骤四步变为了三步,R8将Proguard和D8做的事情合并为了一步,因此很大程度上可以认为R8相当于Proguard + D8。
在这里插入图片描述
下图是R8与Proguard在处理时间、产出包大小上的对比图,可以看出使用R8后,从Java字节码到Dex字节码的构建时间有了较大提升,在产出包的体积方面则和使用Proguard相差不大。
在这里插入图片描述

在后来发布Android Gradle插件3.4.0版本中,R8变为默认启用状态,也就是说,开发者只要升级Android Gradle插件到3.4.0,在打包时使用的优化器就不再是Proguard而是R8了,当然,google也给开发者保留了继续使用Proguard的方法,在grale.properties文件中,根据自身需要,选择添加以下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值