本文已授权微信公众号「玉刚说」独家发布。
欢迎大家来看「Java 混淆那些事」的第四篇,到目前我们现在已经可以进行编写混淆规则了,但是有个很严重问题,我们写的规则会出现很多重复的 keep 规则,我们随便举几个例子。
那么这些问题有没有什么办法来解决呢?有,就是今天我们要讲的过滤器。
先放张上一篇博客提到的图,讲到后面我们需要参考。
过滤器是什么呢?就是类似正则的规则过滤器。
首先我先把几种不同类型的过滤器用几张表格列出来,然后讲述一下功能。这一篇我能用话说明白的绝对不用代码。自我感觉在博客中放代码体验太差了。
符号 | 功能 |
---|---|
? | 可以匹配任意一个字符,但是 package 的分隔符(.)除外,例如: com.example.T?st ,可以匹配 com.example.Test , com.example.T2st ,但是 com.example.T12st 、 com.example.Tst 和 com.example.T.st 不可以。 |
* | 可以匹配任意一部分连续的字符,但是 package 的分隔符(.)除外,例如 com.example.*Test ,可以匹配 com.example.Test , com.example.AnyTest ,但是 com.example.xxx.Test 不可以,还有一个特例 com.example.* 只能匹配当前包下的类, com.example.xxx.Test 就匹配不到。 |
** | 可以匹配任意一部分连续的字符,例如 com** ,可以匹配 com.Test , com.example.Test , com.example.java.Test |
在同一匹配规则中匹配和第 n 个通配符一致的内容。例如: *Any<1> ,可以匹配到 TestAnyTest , TestAnytest 不可以。 |
符号 | 功能 |
---|---|
匹配所有构造方法 | |
匹配所有字段方法 | |
匹配所有方法 | |
* | 匹配所有方法和字段,包括构造方法。 |
? | 匹配方法名称中的任何单个字符。 |
在同一匹配规则中匹配和第 n 个通配符一致的内容。 |
注:
-keep class DownloadClient { <fields>; } 复制代码
-keep class DownloadClient { <methods>; } 复制代码
看到了 、 的用法,参照文章开始的类规范的图可知,我们可以再前面添加 public 之类的关键字,但是后面是添加不了东西的。 的后面必须存在一个参数列表。
符号 | 功能 |
---|---|
% | 匹配所有基本类型 |
? | 匹配类名中的任何单个字符 |
* | 匹配不包含包分隔符的类名的任何部分。 |
** | 匹配类名的任何部分,可能包含任意数量的包分隔符。 |
*** | 匹配所有任何类型 |
... | 匹配任何类型任何数量的参数 |
在同一匹配规则中匹配和第 n 个通配符一致的内容。 |
注:?,* 和 ** 通配符不可以匹配原始类型,比如:int,float。包装类和普通类是可以匹配的,比如:Integer,String。
除了上述和类相关的过滤器之外还有和文件过滤器,如果需要自己独立使用 ProGuard 写配置规则或者需要写其他的配置,那么肯定要写那些文件需要输入,输出到哪等等的问题,往往我们的项目很大不能挨个文件去写规则,所以就需要过滤器。下一章我们介绍一些不常用的 ProGuard 选项,也能用到文件相关的过滤器。
符号 | 功能 |
---|---|
? | 匹配文件名中的任何单个字符。 |
* | 匹配不包含目录分隔符的文件名的任何部分。 |
** | 匹配文件名的任何部分,可能包含任意数量的目录分隔符。 |
到此基本的过滤器我们也大概了解了,大家可以看到有好几个长得一样的过滤器,但是作用在不同地方功能不同,我们仔细去看他们的作用,其实也没有什么本质变化。 那么,我们回归一下先前的两个问题。
-keep class **Event { *; } 复制代码
-keep class ** extends XXX { void x(); } 复制代码
但是 XXX 类被混淆了,如果不想 XXX 被混淆,那就在另写一条匹配规则。