栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java proguard混淆示例和结果

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java proguard混淆示例和结果

前言

混淆基础知识
混淆基础语法

官方指南

看了很多混淆的文章但是对于混淆的前后结果语法对比很模糊,因此写下这篇文章。

-keep

保持类或者成员不被混淆(obfuscate)或者移除(shrink)

案例1

我们工程下就两个类

//MySubLib.java
public class MySubLib {
    public void test() {
    }

    public String name = "hehlo";
    public int age =3;
}
//MySubLib2.java
public class MySubLib2 {

    public String hello = "";
    private int age ;

    public String msgPrint() {
        return hello + "----";
    }

    public static void main(String[] args) {

    }
}

执行以下混淆规则

#MySubLib2这个类不会被混淆移除但是其成员会
-keep public class com.example.mymodule.MySubLib2 {
}

结果

除了MySubLib2其他类都被移除,并且MySubLib2属性都不存在了

案例2

执行以下混淆规则

#MySubLib2这个类不会被混淆移除但是其成员会
-keep public class com.example.mymodule.MySubLib2 {
}

原始类

public class MySubLib2 {

    public String hello = "";
    private String hello2 = "";
    private int age ;

    public String msgPrint() {
        return hello + "----";
    }

    public static void main(String[] args) {

    }
}

结果

public class MySubLib2 {
    public String hello = "";

    public MySubLib2() {
    }
}

案例3

执行以下混淆规则

#MySubLib2这个类不会被混
-keep public class com.example.mymodule.MySubLib2 {
#所有public属性和方法都不混被混淆优化裁剪
 public ;
 public ;
}

原始类

public class MySubLib2 {

    public String hello = "";
    private String hello2 = "";
    private int age;

    public String msgPrint() {
        return hello + "----";
    }

    private String msgPrint2() {
        return hello + "----";
    }

    public static void main(String[] args) {

    }
}


结果

public class MySubLib2 {
    public String hello = "";

    public MySubLib2() {
    }

    public static void main(String[] var0) {
    }

    public String msgPrint() {
        return this.hello + "----";
    }
}


案例4

混淆前


执行混淆:

#com.example.mymodule这个包下的类不会被混淆,但是属性会,并且子包也会被混淆裁剪
-keep public class com.example.mymodule.* {

}

结果

当前语法会导致子包类会被移除

同样环境我们执行一下混淆语法

#com.example.mymodule这个包和子包的类不会被混淆,但是属性方法会被优化移除,
-keep public class com.example.mymodule.** {

}

结果

同样环境我们执行一下混淆语法

#com.example.mymodule这个包和子包的类不会被混淆,并且属性方法都不会被优化和移除,
-keep public class com.example.mymodule.** {
  *;
}

结果

案例5


public class MySubLib2 {

    public String hello = "";
    private String hello2 = "";
    private int age;

    public String msgPrint() {
        return hello + "----";
    }

    private String msgPrint2() {
        return hello + "----";
    }

    private String msgPrint2(int i) {
        return hello + "----";
    }

    public static void main(String[] args) {

    }
}

执行混淆:

#MySubLib2类不会被混淆
-keep public class com.example.mymodule.MySubLib2 {
    #所有返回String私有函数 都不会被混淆,不考虑参数
    private java.lang.String *(...);
}

结果:

public class MySubLib2 {
    public MySubLib2() {
    }

    private String msgPrint2() {
        return "" + "----";
    }

    private String msgPrint2(int var1) {
        return "" + "----";
    }
}

同样的环境执行下面的混淆

#MySubLib2类不会被混淆
-keep public class com.example.mymodule.MySubLib2 {
    #所有返回String私有函数并且第一个参数为int不会被混淆
    private java.lang.String *(int);
}

结果:

public class MySubLib2 {
    public MySubLib2() {
    }

    private String msgPrint2(int var1) {
        return "" + "----";
    }
}

-keepclassmembernames

简短名称 -keepclassmembers

当前语法会让其声明的类成员或者方法名不会被混淆(类名依然会被修改),但是前提是这个属性或者方法在shrink阶段存货下来

环境如下:

//MySubLib.java
public class MySubLib {
    MySubLib2 mySubLib2 = new MySubLib2();

    public void test() {
        //故意引用其内部的一个函数
        System.out.println(mySubLib2.msgPrint2());
    }

    public String name = "hehlo";
    public int age = 3;
}

//MySubLib2.java
public class MySubLib2 {

    public String hello = "xx";
    private String hello2 = "111";
    private int age;

    public String msgPrint() {
        return hello + "----";
    }

    public String msgPrint2() {
        return "zz"+ hello + "----";
    }

    private String msgPrint2(int i) {
        return hello + "----";
    }

    public static void main(String[] args) {

    }
    public void test(java.lang.String d){

    }
}


执行如下混淆:

#利用MySubLib保证MySubLib2不会被shrink阶段移走
#MySubLib内部会引用MySubLib2
-keep public class com.example.mymodule.MySubLib{
  *;
}


-keepclassmembers public class com.example.mymodule.MySubLib2 {
	#这个函数名如果在shrink阶段被保留下来 那么应该保证其函数名不变
    public java.lang.String msgPrint2();
    public java.lang.String msgPrint();
}

结果:


你可以看到MySubLib2类名被改为a,但是msgPrint2函数依然没被混淆,另外注意msgPrint函数被移除了。

同样的环境执行如下混淆:

#利用MySubLib保证MySubLib2不会被shrink阶段移走
#MySubLib内部会引用MySubLib2
-keep public class com.example.mymodule.MySubLib{
  *;
}

-keepclassmembers public class com.example.mymodule.MySubLib2 {
	#成员函数运行随意混淆
}

结果:

public class MySubLib {
    public a mySubLib2;
    public String name;
    public int age;

    public MySubLib() {
        MySubLib var10000 = this;
        MySubLib var10001 = this;
        MySubLib var10002 = this;
        super();
        a var1;
        var1 = new a.();
        var10002.mySubLib2 = var1;
        var10001.name = "hehlo";
        var10000.age = 3;
    }

    public void test() {
        PrintStream var10000 = System.out;
        a var1;
        (var1 = this.mySubLib2).getClass();
        var10000.println("zz" + var1.a + "----");
    }
}

//a.java
public class a {
    public String a = "xx";

    public a() {
    }
}

你可以看到函数体都被优化没了,变成了内联

-keepclasseswithmembernames

简短名称 -keepclasseswithmembers

当前语法会让其声明的类成员或者方法名不会被混淆并且类名也不会被混淆,但是前提是这个类和属性或者方法在shrink阶段存活下来

public class MySubLib {
    MySubLib2 mySubLib2 = new MySubLib2();

    public void test() {
        //故意引用其内部的一个函数
        System.out.println(mySubLib2.msgPrint2());
    }

    public String name = "hehlo";
    public int age = 3;
}

public class MySubLib2 {

    public String hello = "xx";
    private String hello2 = "111";
    private int age;

    public String msgPrint() {
        return hello + "----";
    }

    public String msgPrint2() {
        return "zz"+ hello + "----";
    }

    private String msgPrint2(int i) {
        return hello + "----";
    }

    public static void main(String[] args) {

    }
    public void test(java.lang.String d){

    }
}

结果:

//MySubLib2.java
public class MySubLib2 {
    public String hello = "xx";
    public String hello2 = "111";

    public MySubLib2() {
    }

    public String msgPrint2() {
        return "zz" + this.hello + "----";
    }
}

//MySubLib.java
public class MySubLib {
    public MySubLib2 mySubLib2;
    public String name;
    public int age;

    public MySubLib() {
        MySubLib var10000 = this;
        MySubLib var10001 = this;
        MySubLib var10002 = this;
        super();
        MySubLib2 var1;
        var1 = new MySubLib2.();
        var10002.mySubLib2 = var1;
        var10001.name = "hehlo";
        var10000.age = 3;
    }

    public void test() {
        System.out.println(this.mySubLib2.msgPrint2());
    }
}

你可以看到MySubLib2这个类名和其成员函数都没有被混淆

-assumenosideeffects

高危险操作,慎用.用于移除指定类的函数的调用

原环境

public class MySubLib {
    MySubLib2 mySubLib2 = new MySubLib2();

    @SuppressLint("LogUsage")
    public void test() {
        System.out.printf("----");
        Log.e("hello","hello");
        System.out.printf("++");
    }

    public String name = "hehlo";
    public int age = 3;
}

执行以下混淆

#利用MySubLib不会被shrink阶段移走
-keep public class com.example.mymodule.MySubLib{
  *;
}

# assume no side effects
#删除Log.e等方法的调用
-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(...);
}

结果

public class MySubLib {
    public a mySubLib2;
    public String name;
    public int age;

    public MySubLib() {
        MySubLib var10000 = this;
        MySubLib var10001 = this;
        MySubLib var10002 = this;
        super();
        a var1;
        var1 = new a.();
        var10002.mySubLib2 = var1;
        var10001.name = "hehlo";
        var10000.age = 3;
    }

    @SuppressLint({"LogUsage"})
    public void test() {
        System.out.printf("----");
        System.out.printf("++");
    }
}

你可以可以清晰的看到test中间的Log.e代码被删除

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/332054.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号