Android 代码混淆 选项说明
Posted 匆忙拥挤repeat
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 代码混淆 选项说明相关的知识,希望对你有一定的参考价值。
转载请注明出处:
android 代码混淆 选项说明
http://blog.csdn.net/jjwwmlp456/article/details/44977721 ----------------- 匆忙拥挤repeat
语法规范说明地址:https://stuff.mit.edu/afs/sipb/project/android/sdk/android-sdk-linux/tools/proguard/docs/index.html#manual/usage.html
sdk目录: /sdk/tools/proguard
Input/Output Options 输入/输出 选项
@filename
Short for '-include filename'.
-include filename
递归读取目录中(如果有)文件的 配置:configuration options
-basedirectory directoryname
配置文件的目录 directoryname规则见filename
-injars class_path
输入(即使用的) jar文件路径。作用:对配置的jar文件,要进行混淆
例:-injars "my program.jar":"/your directory/your program.jar"引号可以不要
-outjars class_path
输出 jar 路径
-libraryjars class_path
指定的jar将不被混淆,just run-time jar;注意这里在编译时会进行一次依赖,如果由gradle依赖过了,再配置该项,会造成重复依赖。
-skipnonpubliclibraryclasses
跳过(不混淆) jars中的 非public classes
-dontskipnonpubliclibraryclasses
不跳过(混淆) jars中的 非public classes 默认选项
-dontskipnonpubliclibraryclassmembers
不跳过 jars中的非public classes的members
-keepdirectories [directory_filter]
指定目录 keep 在 out jars中 directory_filter规则见file filter
-target version
java版本 1.0, 1.1, 1.2, 1.3, 1.4, 1.5 (or just 5), 1.6 (or just 6), or 1.7 (or just 7).
-forceprocessing
指定input处理,即使output seems up to date
Keep Options 保持不变的选项
-keep [,modifier,...] class_specification
保持class_specification规则;若有[,modifier,...],则先启用它的规则
-keepclassmembers [,modifier,...]class_specification
保持类的成员:属性(可以是成员属性、类属性)、方法(可以是成员方法、类方法)
-keepclasseswithmembers [,modifier,...] class_specification
与-keep功能基本一致(经测试)
-keepnames class_specification
Short for -keep,allowshrinking class_specification
-keepclassmembernames class_specification
Short for -keepclassmembers,allowshrinking class_specification
-keepclasseswithmembernames class_specification
Short for -keepclasseswithmembers,allowshrinking class_specification
-printseeds [filename]
打印匹配的-keep家族处理的 类和类成员列表,到标准输出。
用Proguard 命令行,能看到输出效果(未测试)
Shrinking Options 压缩选项
shrink,测试后发现会将一些无效代码给移除,即没有被显式调用的代码
-dontshrink
shrink操作默认启用,每个optimization步骤后,都会执行一步shrink。
该选项 表示 不启用 shrink。
测试后发现是全局性的,且即便使用了-keep 开启shrink,也无效
-printusage [filename]
打印被移除的代码,在标准输出
-whyareyoukeeping class_specification
打印 在shrink过程中 为什么有些代码被 keep
Optimization Options 优化选项
基于控制流、数据流分析后,删除、合并一些代码
-dontoptimize
optimization,默认启用
该选项表示 不启用
当不使用该选项时,下面的才有效
-optimizations optimization_filter
根据optimization_filter指定要优化的文件
-optimizationpasses n
优化数量 n
-assumenosideeffects class_specification
如果一个方法有返回值,在调用的时候没使用到它的返回值,那么可能被忽略。
-allowaccessmodification
优化时允许访问并修改类和类的成员的 访问修饰符,可能作用域会变大。
-mergeinterfacesaggressively
竭力合并接口,即使它们的实现类未实现合并后接口的所有方法。
Obfuscation Options 混淆选项
混淆类名、属性名、方法名、变量名等,变成无意义的类似a,b,c,d...的名字
-dontobfuscate
不混淆
-printmapping [filename]
打印 映射旧名到新名
-applymapping filename
打印相关
-obfuscationdictionary filename
指定外部模糊字典
-classobfuscationdictionary filename
指定class模糊字典
-packageobfuscationdictionary filename
指定package模糊字典
-overloadaggressively
过度加载,多个属性和方法使用相同的名字,只是参数和返回类型不同 可能各种异常
-useuniqueclassmembernames
类和类成员都使用唯一的名字
-dontusemixedcaseclassnames
不使用大小写混合类名
-keeppackagenames [package_filter]
保持packagename 不混淆
-flattenpackagehierarchy [package_name]
指定重新打包,所有包重命名,这个选项会进一步模糊包名 好东西
将包里的类混淆成n个再重新打包到一个个的package中
-repackageclasses [package_name]
将包里的类混淆成n个再重新打包到一个统一的package中 会覆盖flattenpackagehierarchy选项
-keepattributes [attribute_filter]
# 混淆时可能被移除下面这些东西,如果想保留,需要用该选项。对于一般注解处理如 -keepattributes *Annotation*
# attribute_filter : Exceptions, Signature, Deprecated, SourceFile, SourceDir, LineNumberTable,
#LocalVariableTable, LocalVariableTypeTable, Synthetic,
#EnclosingMethod, RuntimeVisibleAnnotations, RuntimeInvisibleAnnotations, RuntimeVisibleParameterAnnotations,
#RuntimeInvisibleParameterAnnotations, and AnnotationDefault.
-keepparameternames
-renamesourcefileattribute [string]
-adaptclassstrings [class_filter]
-adaptresourcefilenames [file_filter]
-adaptresourcefilecontents [file_filter]
Preverification Options 预校验选项
-dontpreverify
-microedition
General Options 通用选项
-verbose
打印详细
-dontnote [class_filter]
不打印某些错误
-dontwarn [class_filter]
不打印警告信息
-ignorewarnings
忽略警告,继续执行
-printconfiguration [filename]
打印配置文件
-dump [filename]
指定打印类结构
其他说明
Class Paths : class_path
类路径,unix分隔符为冒号(:),windows分隔符为分号(;)
可以表示的文件类型有:
· a class file or resource file
· a jar file
· a war file
· an ear file
· a zip file
· a directory(structure)
File Names : filename
文件或目录名,可以使用相对或绝对路径
可以使用Java system properties,表示法:<...>
如:<java.home>、<user.home>、<user.dir> 等
File Filters : file_filter
文件过滤。
通配符:
? 匹配任意一个单个字符
* 匹配任意多个字符,不含目录分隔符:unix下为(/),windows下为(\\)
** 匹配任意多个字符,含目录分隔符
还可以使用一个逻辑符号:!
! 表示 求反,除...之外
Filters : package_filter、attribute_filter、class_filter
可以过滤的有:names of files, directories, classes, packages, attributes, optimizations(见下文)
通配符:
? 匹配任意一个单个字符
* 匹配任意多个字符,不含目录分隔符和package分隔符:.
** 匹配任意多个字符,含目录分隔符和package分隔符:.
还可以使用一个逻辑符号:!
! 表示 求反,除...之外
Overview of Keep Options
keep 选项,表示保持 类或类成员(方法和属性) 不变。各选项间的关系:
Keep (保护、保持) | From being removed or renamed (保护 将会删除或重命名) | From being renamed (保护 将重命名) |
Classes and class members | -keep | -keepnames |
Class members only | -keepclassmembers | -keepclassmembernames |
Classes and class members, if class members present | -keepclasseswithmembers | -keepclasseswithmembernames |
每个keep选项 后面都跟一个 class_specification
注意:
· 只指定class时,那么类的成员还是可以被移除、优化、混淆
· 指定了类的某些成员时,那么除这些之外的其它的成员 还是可以被 移除、优化、混淆
Keep Option Modifiers : modifiers
allowshrinking 启用压缩
压缩默认启用
如果 上一条keep 了(即不压缩),而下一条allowshrinking,则还是会压缩,即:会覆盖上面的配置
allowoptimization启用优化
优化默认启用
会覆盖上面的配置
allowobfuscation启用混淆
混淆默认启用
会覆盖上面的配置
例:
-keep public class com.stone.*Activity 保护任意com.stone包下的*Activity
-keep ,allowshrinking public class com.stone.*Activity 启用压缩
Class Specifications 类规范
完整语法
[@annotationtype] [[!]public|final|abstract|@...] [!]interface|class|enumclassname [extends|implements [@annotationtype]classname]
[
[@annotationtype] [[!]public|private|protected|static|volatile|transient...]<fields> | (fieldtype fieldname);
[@annotationtype] [[!]public|private|protected|static|synchronized|native|abstract
|strictfp ...]<methods> |<init>(argumenttype,...) |classname(argumenttype,...) |(returntype methodname(argumenttype,...));
[@annotationtype] [[!]public|private|protected|static ... ] *;
...
]
蓝色的java关键字
[ ] 表示里面的内容是可选的。
@ 表示是一个注解类型 annotationtype的规范与classname类似
...
[[!]public|final|abstract|@ ...] : ...表示可以写上前面选项中的任意一种或多种。不参与语法
(argumenttype,...) :... 参与语法,表示0个或多个任意参数类型
| 表示或
! 表示非
()在表示方法时,才是语法的一部份;其它时候,只是用来分组
classname 需要使用完全限定类名(即含包名的类名)
可以使用如下通配符匹配类名:
? 匹配一个任意字符
* 匹配多个任意字符,不含package分隔符.
** 匹配多个任意字符,含package分隔符.
属性(fields)和方法(methods):
它们的规范与java中的规范类似,只是方法中不需要写上参数名,有参数类型即可
<init> matches any constructor.
<fields> matches any field.
<methods> matches any method.
* matches any field or method. 注意这四个通配符,本身不含 访问修饰符
属性或方法后面都要以分号(;)结尾
属性名或方法名可以使用的通配符:
?匹配任意一个字符
* 匹配任意多个字符
属性或方法类型(类型可以直接写,如果是一个class,则写上class的完全限定名)可以使用的通配符:
% 表示任意基本数据类型,不含void
? 表示匹配用作类型的 class name的任意一个字符
* 任意多个字符,不含package分隔符(.)
** 任意多个字符,含package分隔符(.) 匹配非基本数据类型和非数组类型
例: ** get*() 可匹配com.stone.User getCurUser(),
但不匹配String getName(),也不匹配com.stone.User[ ] getCurUser()。
*** 匹配任意类型
... 表示任意数量的任意参数类型
构造方法中的class name,可以用短类名或含包名的类名
Optimizations : optimization_filter
当不使用-dontobfuscate选项时,则-optimizationsoptimization_filter才有效
optimization_filter 可以使用的通配符:
?任意一个字符 (没啥用)
* 任意多个字符
可以用 ! 表示 非
For example, "code/simplification/variable,code/simplification/arithmetic
" only performs the two specified peephole optimizations.
For example, "!method/propagation/*
" performs all optimizations, except the ones that propagate values between methods.
For example, "!code/simplification/advanced,code/simplification/*
" only performs all peephole optimizations.
optimization_filter 表示的有:
class/marking/final
Marks classes as final, whenever possible.
在任何可能的时候,将类标志为final class
class/merging/vertical
Merges classes vertically in the class hierarchy, whenever possible.
垂直合并类(上下层级的类 进行合并)
class/merging/horizontal
Merges classes horizontally in the class hierarchy, whenever possible.
水平合并类(同一层级的类 进行合并)
(⇒ code/removal/advanced) 表示当前选项是=>后的 前置选项
field/removal/writeonly
Removes write-only fields.
删除只写 属性
field/marking/private
Marks fields as private, whenever possible.
标记属性为private
(⇒ code/simplification/advanced)
field/propagation/value
Propagates the values of fields across methods.
在方法中传播属性值
method/marking/private
Marks methods as private, whenever possible (devirtualization).
标记属性为private(具体化)
(⇒ code/removal/advanced)
method/marking/static
Marks methods as static, whenever possible (devirtualization).
标记方法为static(具体化)
method/marking/final
Marks methods as final, whenever possible.
标记方法为final
(⇒ code/removal/advanced)
method/removal/parameter
Removes unused method parameters.
删除未使用的方法参数
(⇒ code/simplification/advanced)
method/propagation/parameter
Propagates the values of method parameters from method invocations to the invoked methods.
从方法的invocations传递方法参数值到 实际调用方法的地方invoked methods
(⇒ code/simplification/advanced)
method/propagation/returnvalue
Propagates the values of method return values from methods to their invocations.
传递方法的返回值 从方法到它们被调用的地方
method/inlining/short
Inlines short methods.
内联短方法
method/inlining/unique
Inlines methods that are only called once.
内联 仅被调用一次(或者说只被一个地方调用)的短方法
method/inlining/tailrecursion
Simplifies tail recursion calls, whenever possible.
简化尾递归 (尾递归转循环)
code/merging
Merges identical blocks of code by modifying branch targets.
合并相同的代码块
code/simplification/variable
Performs peephole optimizations for variable loading and storing.
变量加载和存储时 使用peephole optimization(窥孔优化)技术
code/simplification/arithmetic
Performs peephole optimizations for arithmetic instructions.
计算指令 用 窥孔优化
code/simplification/cast
Performs peephole optimizations for casting operations.
类型转换 用 窥孔优化
code/simplification/field
Performs peephole optimizations for field loading and storing.
属性加载和存储 用 窥孔优化
(⇒ code/removal/simple)
code/simplification/branch
Performs peephole optimizations for branch instructions.
分支指令 用 窥孔优化
code/simplification/string
Performs peephole optimizations for constant strings.
常量字符串 用 窥孔优化
(best used with code/removal/advanced)
code/simplification/advanced
Simplifies code based on control flow analysis and data flow analysis.
简化代码 基于控制流分析和数据流分析
(⇒ code/removal/exception)
code/removal/advanced
Removes dead code based on control flow analysis and data flow analysis.
删除死代码 基于控制流分析和数据流分析
(⇒ code/removal/exception)
code/removal/simple
Removes dead code based on a simple control flow analysis.
删除死代码 基于一个简单的控制流分析
code/removal/variable
Removes unused variables from the local variable frame.
从本地变量框架中,删除 未使用的变量
code/removal/exception
Removes exceptions with empty try blocks.
当try-catch中,try块内为空时,删除exceptions
code/allocation/variable
Optimizes variable allocation on the local variable frame.
在本地变量框架中 优化变量分配
注意
· 上一句保护,下一句启用modifers, 启用无效; 上一句启用modifiers,下一句保护,保护有效。 重在保护
· 使用了-dontshrink|dontoptimize|dontobfuscate 这些全局选项后,那么再使用相应的kepp modifiers 无效
· 当不使用-dontoptimize选项时,则-optimizations optimization_filter才有效
· 测试发现jdk中就有优化不通过的地方,并且这个优化时间很长时间,还可能造成优化程序不结束(一直在运行,结束不了)
所以一般还是直接使用 -dontoptimize。sdk中的proguard的配置文件也是这么写的。如果你想专业点,自行调试吧~
示例
-dontoptimize #不优化
-dontpreverify #不预校验
#保持源文件和行号的信息,用于混淆后定位错误位置
-keepattributes SourceFile,LineNumberTable
-libraryjars class_path #不处理 class_path指定的文件
-dontusemixedcaseclassnames #不使用大小写混合类名
-dontskipnonpubliclibraryclasses #不跳过jars中的非public classes。在proguard4.5时,是默认选项
-verbose
-flattenpackagehierarchy com.stone.myapplication.interfaces # 将包里的类混淆成n个再重新打包到一个一个的package中
-repackageclasses com.stone.myapplication.interfaces #将包里的类混淆成n个再重新打包到一个统一的package中 会覆盖flattenpackagehierarchy选项
-keepattributes *Annotation* #保持含有Annotation字符串的 attributes
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
#保持 本化方法及其类声明
-keepclasseswithmembernames class *
native <methods>;
#保持view的子类成员: getter setter
-keepclassmembers public class * extends android.view.View
void set*(***);
*** get*();
#保持Activity的子类成员:参数为一个View类型的方法 如setContentView(View v)
-keepclassmembers class * extends android.app.Activity
public void *(android.view.View);
#保持枚举类的成员:values方法和valueOf (每个enum 类都默认有这两个方法)
-keepclassmembers enum *
public static **[] values();
public static ** valueOf(java.lang.String);
#保持Parcelable的实现类和它的成员:类型为android.os.Parcelable$Creator 名字任意的 属性
-keep class * implements android.os.Parcelable
public static final android.os.Parcelable$Creator *;
#保持 任意包名.R类的类成员属性。 即保护R文件中的属性名不变
-keepclassmembers class **.R$*
public static <fields>;
#不警告 support包
-dontwarn android.support.**
-keepattributes Signature #保持签名
#下面三个gson相关
-keep class sun.misc.Unsafe *;
-keep class com.google.gson.examples.android.model.***;
-keep class com.tv.kuaisou.bean.* *;
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
后记:
边翻译,边测试了三四天,头痛,有些什么打印、重命名及不怎么用的选项,实在翻译不下去了。
有些官方上也没有看到示例,比如 外部的混淆字典...
如有失误,请指正。
———————————————————————update 2017-06-30 ——————————————————————————
在使用AndroidStudio时遇到一些其它问题:
1. 当有多个library-module时,如果将混淆配置,放在它们每个之中,以为会像manifest一样,会进行合并,但是它并没有...
这就需要手动的在application-moudle中的build.gradle中加入其它混淆文件的的地址
buildTypes
debug
minifyEnabled false
release
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro', "../submodule/proguard-rules.pro"
signingConfig signingConfigs.release
2. 可以在混淆时指定运行时的 jars(or wars, ears, zips, or directories)的 class_path
例:
-libraryjars libs/ftpserver-core-1.0.6.jar : libs/log4j-1.2.14.jar
以上是关于Android 代码混淆 选项说明的主要内容,如果未能解决你的问题,请参考以下文章
Android 项目的代码混淆,Android proguard 使用说明
Android 安装包优化资源混淆 ( resources.arsc 资源映射表混淆 | resources.arsc 资源映射表二进制格式分析 | 混淆全局字符串池和资源名称字符串池 )