1. Start up

下载并安装proguard,当前是5.3.3,解压并将bin所在目录设置到系统环境变量中,接着你就可以使用命令行工具开始ProGuard之旅了。

1.1 @myconfig.pro / -include myconfig.pro

指定使用myconfig.pro作为ProGuard文件

>proguard @mycofnig.pro

>proguard -include myconfig.pro

1.2 -injars

指定要进行proguard的类文件集合(jar包、aar包、war包、zip包、apk报或者目录都可以)

>proguard -injars in.jar

>proguard -injars in.zip

1.3 -outjars

指定proguard后要输出的类文件集合,可以包含的类型同上

>proguard -outjars out.jar

>proguard -outjars out.zip

1.4 -libraryjars

指定所使用的类依赖的文件集合,可以包含的类型同上 ,注意

>proguard -libraryjars lib.jar

1.5 target

指定要使用的jdk版本,可选项是:1.0、1.1、1.2、1.3、1.4、1.5(或5)、1.6(或6)、1.7(或7)

>proguard -target 8

1.6 总之就是这一套技能打下去就好了。

proguard -include myconfig.pro -injars in.jar -libraryjars rt.jar -outjars out.jar -verbose

2. Keep options(保留选项)

为了方便学习,本着实践出真知的想法,我们开始定义一些类。

// MainClass.java

public class MainClass{

public static void main(String[] args){

private User user = new User(23333,"Shaoxia",new Clothes("uniqlo","jeans","straw hat"));

System.out.println(user.intro());

}

}

//User.java

public class User{

private String name;

private int id;

private Clothes clothes;

public User(int id,String name, Clothes clothes){

this.id = id;

this.name = name;

this.clothes = clothes;

}

public String intro(){

return this.toString();

}

public void setName(String name){

this.name = name;

}

public String getName(){

return this.name;

}

public void setId(int id){

this.id =id;

}

public int getId(){

return this.id;

}

@Override

public String toString(){

return String.format("[name: %s,id: %d]",name,id);

}

}

// Clothes.java

public class Clothes{

private String shirt;

private String trousers;

private String hat;

public Clothes(String shirt, String trousers, String hat){

this.shirt = shirt;

this.trousers = trousers;

this.hat = hat;

}

public String getShirt(){

return this.shirt;

}

public String getTrousers(){

return this.trousers;

}

public String getHat(){

return this.hat;

}

}

2.1 -keep [,modifier,...] specification

指定不混淆指定的类,包括类名和成员名。

//myconfig.pro

-keep class MainClass{*;}

-keep class User{*;}

运行proguard后再使用jd-gui进行反编译,结果如下:

// MainClass

import java.io.PrintStream;

public class MainClass

{

public static void main(String[] paramArrayOfString)

{

User localUser = new User(23333, "Shaoxia", new a("uniqlo", "jeans", "straw hat"));

System.out.println(localUser.intro());

}

}

// User

public class User

{

private String name;

private int id;

private a clothes;

public User(int paramInt, String paramString, a parama)

{

this.id = paramInt;

this.name = paramString;

this.clothes = parama;

}

public String intro()

{

return toString();

}

public void setName(String paramString)

{

this.name = paramString;

}

public String getName()

{

return this.name;

}

public void setId(int paramInt)

{

this.id = paramInt;

}

public int getId()

{

return this.id;

}

public String toString()

{

return String.format("[name: %s,id: %d]", new Object[] { this.name, Integer.valueOf(this.id) });

}

}

// Clothes

public class a

{

private String a;

private String b;

private String c;

public a(String paramString1, String paramString2, String paramString3)

{

this.a = paramString1;

this.b = paramString2;

this.c = paramString3;

}

}

2.2 -keepclassmembers [, mobifier,...] class spcification

指定保留指定类的的成员,包括成员变量和成员方法。

//myconfig.pro

-keepclassmembers class Clothes{*;}

于是乎,Clothes的所有成员就都被保留了。

public class a

{

private String shirt;

private String trousers;

private String hat;

public a(String paramString1, String paramString2, String paramString3)

{

this.shirt = paramString1;

this.trousers = paramString2;

this.hat = paramString3;

}

public String getShirt()

{

return this.shirt;

}

public String getTrousers()

{

return this.trousers;

}

public String getHat()

{

return this.hat;

}

}

2.3 keepclasseswithmembers [, modifier,...] class specification

指定不混淆类和成员。这时Clothes就回到原有的模样,除了方法参数变了之外。

2.4 keepnames

保留类名,是 -keep, allowshrinking class specification的简写,意思就是如果该类没有在shrink阶段被移除的话,就不混淆其类名。

-keepnames class Clothes{*;}

混淆结果:

public class Clothes

{

private String shirt;

private String trousers;

private String hat;

public Clothes(String paramString1, String paramString2, String paramString3)

{

this.shirt = paramString1;

this.trousers = paramString2;

this.hat = paramString3;

}

}

2.5 -keepclassmembernames class specification

指定保留类的成员名,是-keepclassmembers, allowshrinking class specification 的简写。

-keepclassmembernames class Clothes{*;}

混淆结果是:

public class a

{

private String shirt;

private String trousers;

private String hat;

public a(String paramString1, String paramString2, String paramString3)

{

this.shirt = paramString1;

this.trousers = paramString2;

this.hat = paramString3;

}

}

2.6 -keepclasseswithmembernames class specification

-keepclasseswithmembers, allowshrinking class specification的简写,指定保留类名和类成员名,除非被shrink掉了。

-keepclasseswithmembernames class User{*;}

混淆结果是:

public class User

{

private String name;

private int id;

private a clothes;

public User(int paramInt, String paramString, a parama)

{

this.id = paramInt;

this.name = paramString;

this.clothes = parama;

}

public String intro()

{

return toString();

}

public String toString()

{

return String.format("[name: %s,id: %d]", new Object[] { this.name, Integer.valueOf(this.id) });

}

}

2.7 -printseeds [filename]

打印出那些被keep住的类和成员,结果输出到指定文件里。

-keep class MainClass{*;}

-keepclasseswithmembernames class User{*;}

-printseeds whatkeeped.txt

输出结果是:

MainClass

MainClass: MainClass()

MainClass: void main(java.lang.String[])

User

User: java.lang.String name

User: int id

User: Clothes clothes

User: User(int,java.lang.String,Clothes)

User: java.lang.String intro()

User: void setName(java.lang.String)

User: java.lang.String getName()

User: void setId(int)

User: int getId()

User: java.lang.String toString()

3. Shrink Options(压缩选项)

3.1 -dontshrink

不压缩。压缩功能会把除了被keep住和直接或间接依赖的类和成员会保留外,其他的类或成员都会被移除。

3.2 -printusage [filename]

指定输出那些没用的代码(dead code)到文件中。

Clothes:

12:12:public java.lang.String getShirt()

16:16:public java.lang.String getTrousers()

20:20:public java.lang.String getHat()

User:

17:18:public void setName(java.lang.String)

21:21:public java.lang.String getName()

25:26:public void setId(int)

29:29:public int getId()

3.3 -whyareyoukeeping class specification

指定打印一些日志告诉你为什么特定的类或者类成员在压缩阶段被保留了。

-whyareyoukeeping class User{

public java.lang.String intro(...);

}

控制台输出:

User

is invoked by MainClass: void main(java.lang.String[]) (4:6)

is kept by a directive in the configuration.

User: java.lang.String intro() (13:13)

is invoked by MainClass: void main(java.lang.String[]) (4:6)

is kept by a directive in the configuration.

4. Optimization options(优化选项)

4.1 -dontoptimize

不优化。默认优化是开启的,所有的方法都会在字节码级别进行优化。

4.2 -optimizations optimization filter

这是一个高级选项,会进行细粒度的优化。

4.3 optimizationpasses n

指定进行优化的通道,默认是单通道。如果一个优化通道后没有提升,那么优化就结束了。

4.4 -assumenosideeffeccts class specification

假定优化对指定的类没有副作用。意思就是说开启该选项,ProGuard会移除对程序功能没有影响的代码,比如打印日志的代码,这个选项很危险,要慎重使用。

-assumenosideeffects class android.util.Log {

public static boolean isLoggable(java.lang.String, int);

public static int v(...);

public static int i(...);

public static int w(...);

public static int d(...);

public static int e(...);

}

4.5 -allowaccessmodification

允许修改限定符,类以及类成员的修饰符在优化步骤会被加宽。这个选项不适合那些类库,因为会导致本来为是no public的变成public,导致API暴露。

4.6 -mergeinterfacesaggressively

这个选项允许接口被合并,能减少类的数量,从而达到优化的目的。当然这并不总是很用,在JIT编译器中,反而会降低性能,因为JIT倾向于多接口少实现。

5. Obfuscation option(混淆选项)

5.1 -dontobfuscate

不混淆。默认启用混淆,类和类成员名会变成短小且随机的名字。可通过keep选项来保留一些。

5.2 -printmapping [filename]

打印混淆前后的名称对应关系到文件中,以便crash后进行对照。例中打印的结果是:

Clothes -> a:

void (java.lang.String,java.lang.String,java.lang.String) ->

MainClass -> MainClass:

void () ->

void main(java.lang.String[]) -> main

User -> User:

java.lang.String name -> name

int id -> id

Clothes clothes -> clothes

void (int,java.lang.String,Clothes) ->

java.lang.String intro() -> intro

java.lang.String toString() -> toString

5.3 -applymapping filename

指定重用之前生成的mapping文件,这样原先混淆的类名和成员名就不会再变了,这个对于那些增量式打补丁式的混淆很有用。当然如果项目结构从根本上就变动了,那么用这种方式就很有风险了,这时候可以使用-useuniqueclasssmembernames来降低风险。

5.4 obfuscationdictionary filename

混淆字典。默认混淆使用的是a、b、c之类的作为类名和文件名。使用这个选项可以自己指定一套字典供混淆使用。不过空白符、 标点符号、重复的单词和#号后面的注释会被忽略。我试了下:

-obfuscationdictionary dict.txt

果然:

public final class b

{

private String Fuck;

private int Fck = 23333;

public b(int paramInt, String paramString, a parama)

{

this.Fuck = paramString;

}

public final String toString()

{

return String.format("[name: %s,id: %d]", new Object[] { this.Fuck, Integer.valueOf(this.Fck) });

}

}

5.5 -packageobfuscationdictionary filename

将指定文件里的所有合法的单词作为混淆的包名使用。

5.6 -overloadaggressively

强制进行方法重载,多个不用的成员变量或者方法会被混淆成同一名字,只要它们的参数和返回值不用即可。

5.7 -useuniqueclassmembernames

指定原本一样的成员名,混淆后还是一样;原本不一样的成员名,混淆后还是不同。这样对于后面的mapping和增量更新很有用。

5.8 -dontusemixedcaseclassnames

不要生成大小写混合的类名,这样就不至于在一些大小写不敏感的系统上软件包不可用。注意:默认情况下,混淆会生成大小写混合的类名的。

5.9 -keeppackagenames [package filter]

指定不要对过滤器中的包名进行混淆。包名过滤器是一个可以包含?、和等通配符在内的使用逗号分隔的包名列表。

5.10 -flattenpackagehierarchy [package_name]

指定重打包,将所有的包移动到单个指定的父级包名。如果没有指定或者指定了空字符串,那么会被移动到根包。

5.11 -repackageclasses [package_name]

指定重打包所有被混淆的类文件,将所有的类移动到单个指定的包。该选项重写自-flattenpackagehierarchy。

5.12 -keepattributes [attribute-filter]

指定保留列表中的属性,列表仍然是可以使用?、和*的用逗号分隔的属性。

-keepattributes Exceptions,InnerClasses,Signature,Deprecated,

SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

5.13 -keepparameternames

保留参数名。这对于类库来说很有用,因为可以展示有意义的参数名供调用者调用。

5.14 -renamesourcefileattribute [string]

指定一个字符串常量作为类文件的源文件属性的前缀。

5.15 -adaptclassstrings [class filter]

更改类字符串。开启该选项会将跟类名相符的字符串常量也一并混淆了。-adaptresourcefilenames [file filter]和-adaptresourcefilecontents [file filter]见名知意。

6. Preverification options(预校验)

6.1 -dontpreverify

不要预校验。预校验在Java Micro Edition 或者Java 6以上可用。在Java 6和Android上是可选项,在Java Micro Edition 和Java 7以上是必选的。关闭预校验可以减少处理时间。

6.2 -microedition

指定处理的类文件是面向Java Micro Edition的。

7. 通用选项

7.1 -verbose

控制台输出详细的Proguard日志。

7.2 -dontnote [class filter]

不提示过滤器中的类名。

7.3 -dontwarn [class filter]

不要警告过滤器中的类,忽略警告继续proguard。这个对于忽略第三方类库中的类的警告很有用。

7.4 -ignorewarnings

控制台输出所有未解析的应用和其他重要的问题,但是忽略,继续执行proguard。

7.5 -printconfiguration [filename]

指定输出所有的配置到指定文件中。这些配置包括混淆文件和替换的变量。

7.6 -dump [filename]

写出处理后的类文件的结构。

-injars in.jar

-dontshrink

-dontoptimize

-dontobfuscate

-dontpreverify

-dump

参考

proguard java 教程,ProGuard 初探,新手入门必知必会相关推荐

  1. android java教程_[Java教程]Android开发快速入门

    [Java教程]Android开发快速入门 0 2020-12-22 18:01:40 Xamarin.Android 应用程序剖析 以下屏幕截图列出了解决方案的内容. 下面是一个解决方案资源管理器, ...

  2. 脑残式网络编程入门(三):HTTP协议必知必会的一些知识

    为什么80%的码农都做不了架构师?>>>    本文原作者:"竹千代",原文由"玉刚说"写作平台提供写作赞助,原文版权归"玉刚说&q ...

  3. SpringBoot入门到精通_第6篇 _必知必会

    接上一篇:SpringBoot入门到精通_第5篇 _SpringBoot Actuator监控 https://blog.csdn.net/weixin_40816738/article/detail ...

  4. Java架构师必知必会,带走不谢

    可以说,Java是现阶段中国互联网公司中,覆盖度最广的研发语言,掌握了Java技术体系,不管在成熟的大公司,快速发展的公司,还是创业阶段的公司,都能有立足之地. 成为Java架构师,需要掌握哪些技能呢 ...

  5. MySQL必知必会教程:深入理解MySQL技术内幕

    2019独角兽企业重金招聘Python工程师标准>>> MySQL必知必会教程:深入理解MySQL技术内幕 作为最流行的开源数据库软件之一,MySQL数据库软件已经是广为人知了.当前 ...

  6. java的标量和聚合量_第5节:Java基础 - 必知必会(下)

    第5节:Java基础 - 必知必会(下) 本小节是Java基础篇章的第三小节,主要讲述Java中的Exception与Error,JIT编译器以及值传递与引用传递的知识点. 一.Java中的Excep ...

  7. SpringBoot入门到精通_第7篇 _必知必会总结

    接上一篇:SpringBoot入门到精通_第6篇 _必知必会

  8. asp sql ip地址排序_SQL必知必会读书笔记,30分钟入门SQL!

    点击上方SQL数据库开发,关注获取SQL视频教程 SQL专栏 SQL数据库基础知识汇总 SQL数据库高级知识汇总 来源:https://segmentfault.com/p/1210000011760 ...

  9. java面试必知必会

    java面试必知必会 面向对象 成员变量成员方法 Integer相关 double 和 Double相关 多态,向上转型 hashcode.==.equals比较 java中子类继承父类时是否继承构造 ...

最新文章

  1. entjs 键盘监听
  2. 网络yum网址:http://mirrors.163.com/.help/
  3. 采购部管理--餐饮原料的验收管理
  4. 弹层蒙版(mask),ios滚动穿透,我们项目的解决方案
  5. RPC调用框架比较分析
  6. 在C#中使用RESTful API的几种好方法
  7. debug.keystore文件找不到
  8. centOS下JDK1.8的安装
  9. PL/SQL Developer自动补全SQL技巧
  10. vim学习 07——跳转缩进
  11. SpringMVC+MyBatis整合——事务管理
  12. 发的楷体怎么写_小学生硬笔书法怎么练
  13. 关于idea中运行maven项目报错显示找不到包或符号的问题——终极方案
  14. json字符串数组转json数组
  15. 毕业设计不要再做 XX 管理系统了
  16. Threejs中文文档
  17. 读者提问:如何提高效率?
  18. 深入php redis pconnect
  19. 插入SD卡,复制粘贴不了,原来是这个原因造成的
  20. 使用uniapp开发, 引入腾讯位置服务

热门文章

  1. 「万字长文」谈认知差异——理解层次中的“金字塔”
  2. 怎么引css样式,jsp怎么引入css样式?
  3. 通过Flash上传文件提示出错:onHTTPError
  4. 版本更新android联想,终于升级到Android10,联想ZUI11.5 内测版上线
  5. 加工工艺(二)钣金加工、型材板材、加强筋、塑料产品材料
  6. 疫情之下,别乱接私活,某码农就被单位开除了!
  7. ARP协议/ARP攻击与防御
  8. 魔兽世界9.0主播最多的服务器,魔兽9.0来了!首日多个服务器爆满,有玩家排了4小时也没登上!...
  9. 【linux】linux中fork()详解(实例讲解)|fork的运行机制
  10. 四十岁是中年危机还是中年过渡