Proguard的Keep使用方法

本文详细介绍了 ProGuard 的工作原理及如何使用 keep 配置来保护特定的类和成员不被混淆或移除。同时提供了不同 keep 命令的具体用法示例。

背景知识

Java代码存在互相引用的关系,构成一个网状关系.(个人理解)引用又分为两种:普通引用字符串引用(例如反射,native方法等).而java代码的执行入口点必然是采用的字符串引用(例如main等方法),因为外部想要执行此代码必须知道一个明确的入口点名字.

为了表述准确,类的成员变量下文称为域(Field),类的方法和成员变量统称成员(Member).

Proguard流程

  1. 压缩Shrunk:根据所有入口点建立引用关系网,去除网外的所有代码.

  2. 优化Optimize:对入口点以外所有的方法进行分析,将其中一部分方法变为final的,static的,private的或者内联的,从而提高执行效率.

  3. 入口点以外的类,方法,成员重构为简短的名字,可以进一步减小生成文件的大小并且混淆代码.

  4. Preverify:此处不讨论.

Proguard能够准确识别普通引用关系,但是只能识别部分典型的字符串引用(Class.forName方法等).而通过字符串引用的内容绝对不能改名字或者移除,所以就要使用keep配置proguard:

keep怎样使用

keep一共就有三个

  1. -keep [,modifier,…] class_specification

  2. -keepclassmembers [,modifier,…] class_specification

  3. -keepclasseswithmembers [,modifier,…] class_specification

其中modifier为可选配置,具体意义见下文,class_specification是类和成员的模板,用来指定应用keep规则的若干类及其成员.

  1. -keep可以保留指定的类名以及成员(就是把其当做应用的入口点)
  2. -keepclassmembers只能保留住成员而不能保留住类名
  3. -keepclasseswithmembers可以根据成员找到满足条件的所有类而不用指定类名(这样的类必定拥有所列出的所有成员),可以保留类名和成员名

不配置modifier时,上面的语句可以使保留的内容不被移除优化和混淆.

使用modifier

modifier共有三个可选值:

  • allowshrinking允许其被压缩,就是说指定的内容有可能被移除,但是如果没有被移除的话它也不会在后续过程中被优化或者混淆.
  • allowoptimization允许其被优化,但是不会被移除或者混淆(使用情况较少)
  • allowobfuscation允许其被混淆,但是不会被移除或者优化(使用情况较少)

class_specification规则

class_specification是类和成员的一种模板,只有符合此模板的类和成员才会被应用keep规则.

class_specification的一个复杂的示例 
这里写图片描述

[]内的内容是可选的, …表示可以有若干个前面紧邻项.

  • class可以指代任意类和接口,interface指明为接口,enum指明为枚举,在interface或enum前添加!指明为非interface或非enum.
  • classname必须用全名,例如java.lang.String.可以使用正则表达式:

    • ?表示类名中的任意单个字符,但是不包括分割符(.)
    • *表示类名中的任意多个字符,但是不包括分隔符(.)
    • **表示类名中的任意多个字符,包括分隔符(.)

    可以在类名前面添加!为取非之意.为了兼容旧版本以及使用方便,类名*表示所有类(无论其在哪个包下).

  • extends和implements关键字是等价的

  • @指明类或成员具有某些注解

由于指定成员的规则较为复杂,下面单列一节

class_specification中指定成员

成员是java样式的,但是方法参数只有参数类型而没有参数名称,成员可以有以下样式(方法没有返回值,并且只有有参数列表)

  • <init> 代表任意构造方法.
  • <fields> 代表任意域.
  • <methods> 代表任意方法.
  • * 代表任意成员(包括成员变量和方法).

成员可以使用正则表达式

  • ? 代表方法中的任意单个字符.
  • * 代表方法中的任意多个字符.

成员部分描述类型时可以使用以下通配符

  • % 表示任意基本类型(int,char等,但是不包括void).
  • ? 表示类名中的任意单个字符.
  • * 表示类名中的任意多个字符,不包括分隔符(.).
  • ** 表示类名中的任意多个字符,包括分隔符(.).
  • *** 表示任意类型.
  • ... 表示任意多个任意类型的参数.

注意?*和**无法匹配基本类型,只有***可以匹配任意维度的数组类型,例如** get*()*可以匹配java.lang.Object getObject()但是不能匹配float getFloat()也不能匹配java.lang.Object[] getObjects()

构造函数既可以通过短名字(不含包名)指定,也可以通过全名指定.

另外三个keep

  • -keepnames class_specification是-keep,allowshrinking class_specification的缩写
  • -keepclassmembernames class_specification是-keepclassmembers,allowshrinking class_specification的缩写
  • -keepclasseswithmembernames class_specification是-keepclasseswithmembers,allowshrinking class_specification的缩写

这里写图片描述

Tips

一般如果不了解应该采用哪一个keep的话就使用-keep,它可以keep住类名和成员名不被移除和修改名字 
注意:指定了keep的类而没有指定成员则只会keep类名,成员名有可能被移除或混淆

示例1

-keep class com.test.MainActivity$Item{ 
*; 

可以keep内部类(仍然为内部类),类名和成员名都没有变

示例2

keep程序入口点

-keep public class mypackage.MyMain { 
public static void main(java.lang.String[]); 
}

参考资料

推荐到极客头条
0
0
 
 
id="iframeu2998112_0" src="http://pos.baidu.com/gcvm?rdid=2998112&dc=3&di=u2998112&dri=0&dis=0&dai=3&ps=4426x563&dcb=___adblockplus&dtm=HTML_POST&dvi=0.0&dci=-1&dpt=none&tsr=0&tpr=1498550929195&ti=Proguard%E7%9A%84Keep%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%20-%20wyzzgo%E7%9A%84%E6%8A%80%E6%9C%AF%E5%8D%9A%E5%AE%A2%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20youkuaiyun.com&ari=2&dbv=2&drs=1&pcs=1903x911&pss=1903x4442&cfv=0&cpl=5&chi=7&cce=true&cec=UTF-8&tlm=1498550930&rw=911&ltu=http%3A%2F%2Fblog.youkuaiyun.com%2Fwyzzgo%2Farticle%2Fdetails%2F54143696&ecd=1&uc=1920x1040&pis=-1x-1&sr=1920x1080&tcn=1498550930&qn=35acd6475205489e&tt=1498550929093.1130.1267.1269" width="960" height="90" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="border-width: 0px; border-style: initial; vertical-align: bottom; margin: 0px; width: 960px; height: 90px;">
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值