防止 ProGuard 评估数学表达式并删除 Android 中未使用的指令

Preventing ProGuard from evaluating mathematical expressions and removing unused instructions in Android

我正在学习如何在 Android 中使用 ProGuard,在反编译调试 APK(使用 ProGuard 使用构建)后我注意到 ProGuard 删除了未使用的指令并计算数学表达式,例如: 如果我在使用 ProGuard 之前使用这行代码:

Integer JunkCode6666 = new Integer(Integer.MIN_VALUE+Integer.MAX_VALUE+1);

使用ProGuard后变成这样:

num = new Integer(0);

我想知道有没有办法保持原来的方式,这是为了混淆目的。如果有办法阻止 ProGuard 删除未使用的指令。谢谢。

我刚刚通过编译这个 class without proguard

进行了检查
public class Foo {

    final Integer bar = new Integer(Integer.MIN_VALUE+Integer.MAX_VALUE+1);

}

编译构造函数是

  public <init>()V
   L0
    LINENUMBER 1 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
   L1
    LINENUMBER 3 L1
    ALOAD 0
    NEW java/lang/Integer
    DUP
    ICONST_0 // <--- evaluated expression result
    INVOKESPECIAL java/lang/Integer.<init> (I)V
    PUTFIELD Foo.bar : Ljava/lang/Integer;
    RETURN
   L2
    LOCALVARIABLE this LFoo; L0 L2 0
    MAXSTACK = 4
    MAXLOCALS = 1

所以它不是混淆器,而是 Java 编译器,这是因为 Integer 的构造函数中的值是 constant expression 并且在优化编译时间。

例如,您可以检查编译 class

的其他版本
public class Foo {

    final Integer bar = new Integer(getA()+getB()+1);

    private int getA(){
        return Integer.MIN_VALUE;
    }

    private int getB(){
        return Integer.MAX_VALUE;
    }
}

将导致不同的构造函数

  public <init>()V
   L0
    LINENUMBER 1 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
   L1
    LINENUMBER 3 L1
    ALOAD 0
    NEW java/lang/Integer
    DUP
    ALOAD 0
    INVOKESPECIAL Foo.getA ()I
    ALOAD 0
    INVOKESPECIAL Foo.getB ()I
    IADD
    ICONST_1
    IADD
    INVOKESPECIAL java/lang/Integer.<init> (I)V
    PUTFIELD Foo.bar : Ljava/lang/Integer;
    RETURN
   L2
    LOCALVARIABLE this LFoo; L0 L2 0
    MAXSTACK = 5
    MAXLOCALS = 1

如您所见,在第二个版本中,实际上执行了 2 个加法,因为值是从方法调用中获得的,因此不再是常量。