Java 是一种跨平台的、解释型语言,Java 源代码编译成中间”字节码”存储于 class 文件中。由于跨平台的需要,Java 字节码中包括了很多源代码信息,如变量名、方法名,并且通过这些名称来访问变量和方法,这些符号带有许多语义信息,很容易被反编译成 Java 源代码。为了防止这种现象,我们可以使用 Java 混淆器对 Java 字节码进行混淆。
语法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
-include {filename} 从给定的文件中读取配置参数 -basedirectory {directoryname} 指定基础目录为以后相对的档案名称 -injars {class_path} 指定要处理的应用程序jar,war,ear和目录 -outjars {class_path} 指定处理完后要输出的jar,war,ear和目录的名称 -libraryjars {classpath} 指定要处理的应用程序jar,war,ear和目录所需要的程序库文件 -dontskipnonpubliclibraryclasses 指定不去忽略非公共的库类。 -dontskipnonpubliclibraryclassmembers 指定不去忽略包可见的库类的成员。 保留选项 -keep {Modifier} {class_specification} 保护指定的类文件和类的成员 -keepclassmembers {modifier} {class_specification} 保护指定类的成员,如果此类受到保护他们会保护的更好 -keepclasseswithmembers {class_specification} 保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。 -keepnames {class_specification} 保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除) -keepclassmembernames {class_specification} 保护指定的类的成员的名称(如果他们不会压缩步骤中删除) -keepclasseswithmembernames {class_specification} 保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后) -printseeds {filename} 列出类和类的成员-keep选项的清单,标准输出到给定的文件 压缩 -dontshrink 不压缩输入的类文件 -printusage {filename} -dontwarn 如果有警告也不终止 -whyareyoukeeping {class_specification} 优化 -dontoptimize 不优化输入的类文件 -assumenosideeffects {class_specification} 优化时假设指定的方法,没有任何副作用 -allowaccessmodification 优化时允许访问并修改有修饰符的类和类的成员 混淆 -dontobfuscate 不混淆输入的类文件 -printmapping {filename} -applymapping {filename} 重用映射增加混淆 -obfuscationdictionary {filename} 使用给定文件中的关键字作为要混淆方法的名称 -overloadaggressively 混淆时应用侵入式重载 -useuniqueclassmembernames 确定统一的混淆类的成员名称来增加混淆 -flattenpackagehierarchy {package_name} 重新包装所有重命名的包并放在给定的单一包中 -repackageclass {package_name} 重新包装所有重命名的类文件中放在给定的单一包中 -dontusemixedcaseclassnames 混淆时不会产生形形色色的类名 -keepattributes {attribute_name,...} 保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses. -renamesourcefileattribute {string} 设置源文件中给定的字符串常量 |
不能混淆的代码
顾名思义,不能混淆代码如果被混淆了,就会出现错误。
- 需要反射的代码
- 系统接口
- Jni接口
- 需要序列号和反序列化的代码(即实现Serializable接口的JavaBean)
- 与服务端进行元数据交互的JavaBean(JSON、XML中对应的类)
常见错误
1) Proguard returned with error code 1. See console
更新proguard版本
android-support-v4 不进行混淆
添加缺少相应的库
2) 使用gson包解析数据时,出现 missing type parameter 异常
在 proguard-project.txt 中添加
-dontobfuscate
-dontoptimize
在 proguard-project.txt 中添加
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.* { ; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.* { ; }
3) 类型转换错误
在 proguard-project.txt 中添加
-keepattributes Signature
4) 空指针异常
混淆过滤掉相关类与方法
5) java.lang.reflect.UndeclaredThrowableException
-keep interface com.dev.impl.**
6) Error: Unable to access jarfile ..libproguard.jar
路径问题
7) java.lang.NoSuchMethodError
这也是最常见的问题,因为找不到相关方法,方法被混淆了,混淆过滤掉相关方法便可。
下面是我实际项目中的混淆配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
-include {filename} 从给定的文件中读取配置参数 -basedirectory {directoryname} 指定基础目录为以后相对的档案名称 -injars {class_path} 指定要处理的应用程序jar,war,ear和目录 -outjars {class_path} 指定处理完后要输出的jar,war,ear和目录的名称 -libraryjars {classpath} 指定要处理的应用程序jar,war,ear和目录所需要的程序库文件 -dontskipnonpubliclibraryclasses 指定不去忽略非公共的库类。 -dontskipnonpubliclibraryclassmembers 指定不去忽略包可见的库类的成员。 保留选项 -keep {Modifier} {class_specification} 保护指定的类文件和类的成员 -keepclassmembers {modifier} {class_specification} 保护指定类的成员,如果此类受到保护他们会保护的更好 -keepclasseswithmembers {class_specification} 保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。 -keepnames {class_specification} 保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除) -keepclassmembernames {class_specification} 保护指定的类的成员的名称(如果他们不会压缩步骤中删除) -keepclasseswithmembernames {class_specification} 保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后) -printseeds {filename} 列出类和类的成员-keep选项的清单,标准输出到给定的文件 压缩 -dontshrink 不压缩输入的类文件 -printusage {filename} -dontwarn 如果有警告也不终止 -whyareyoukeeping {class_specification} 优化 -dontoptimize 不优化输入的类文件 -assumenosideeffects {class_specification} 优化时假设指定的方法,没有任何副作用 -allowaccessmodification 优化时允许访问并修改有修饰符的类和类的成员 混淆 -dontobfuscate 不混淆输入的类文件 -printmapping {filename} -applymapping {filename} 重用映射增加混淆 -obfuscationdictionary {filename} 使用给定文件中的关键字作为要混淆方法的名称 -overloadaggressively 混淆时应用侵入式重载 -useuniqueclassmembernames 确定统一的混淆类的成员名称来增加混淆 -flattenpackagehierarchy {package_name} 重新包装所有重命名的包并放在给定的单一包中 -repackageclass {package_name} 重新包装所有重命名的类文件中放在给定的单一包中 -dontusemixedcaseclassnames 混淆时不会产生形形色色的类名 -keepattributes {attribute_name,...} 保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses. -renamesourcefileattribute {string} 设置源文件中给定的字符串常量 |
不能混淆的代码
顾名思义,不能混淆代码如果被混淆了,就会出现错误。
- 需要反射的代码
- 系统接口
- Jni接口
- 需要序列号和反序列化的代码(即实现Serializable接口的JavaBean)
- 与服务端进行元数据交互的JavaBean(JSON、XML中对应的类)
常见错误
1) Proguard returned with error code 1. See console
更新proguard版本
android-support-v4 不进行混淆
添加缺少相应的库
2) 使用gson包解析数据时,出现 missing type parameter 异常
在 proguard-project.txt 中添加
-dontobfuscate
-dontoptimize
在 proguard-project.txt 中添加
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.* { ; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.* { ; }
3) 类型转换错误
在 proguard-project.txt 中添加
-keepattributes Signature
4) 空指针异常
混淆过滤掉相关类与方法
5) java.lang.reflect.UndeclaredThrowableException
-keep interface com.dev.impl.**
6) Error: Unable to access jarfile ..libproguard.jar
路径问题
7) java.lang.NoSuchMethodError
这也是最常见的问题,因为找不到相关方法,方法被混淆了,混淆过滤掉相关方法便可。
下面是我实际项目中的混淆配置: