【问题标题】:Proguard removing member field initializationProguard 删除成员字段初始化
【发布时间】:2015-12-12 06:44:37
【问题描述】:

我的 Proguard 发布版本正在剥离我的成员字段的初始化值。这导致我的默认值丢失,导致我的调试和发布版本之间的行为不同。我怎样才能阻止这种情况发生?

这是我的源代码

public class MyClass implements Serializable {
    private static final long serialVersionUID = 1L;

    @SerializedName("myField")
    private boolean myFieldEnabled = true;

    public boolean isMyFieldEnabled() {
        return myFieldEnabled;
    }

    public void setMyFieldEnabled(boolean myFieldEnabled) {
        this.myFieldEnabled = myFieldEnabled;
    }

    ...

混淆后的代码如下所示(移除了 setter 和 getter):

public final class ai implements Serializable
{
    private static final long serialVersionUID = 1L;
    @z(x="myField")
    public boolean myFieldEnabled;

这是我的 build.gradle 中的一个 sn-p:

release {
    minifyEnabled true
    shrinkResources false
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'custom-proguard-rules-optimize.pro'
}

以下是我的自定义规则(来自 custom-proguard-rules-optimize.pro)中的关键 Proguard 优化规则:

# Disable the "code/allocation/variable" optimizations to workaround a
# Proguard bug.  Source: http://stackoverflow.com/a/7587680/112705
-optimizations !code/simplification/arithmetic,field/removal/writeonly,!class/merging/*,!code/allocation/variable
-allowaccessmodification

以下是我们正在使用的 Android 默认规则中的关键 Proguard 优化规则(来自 proguard-android-optimize.txt):

-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
-optimizationpasses 5

我检查了the Proguard optimizations documentation,但没有看到涵盖此问题的优化或混淆选项。

更新

  • !field/* 添加到我们的优化中并没有帮助 - 该字段似乎仍然没有被初始化。希望这种优化已经从 Android 默认的 Proguard 规则中得到了体现...
  • 删除 field/removal/writeonly 没有帮助。
  • 添加 !code/simplification/field 没有帮助。

【问题讨论】:

  • 首先使用“proguard-android.txt”而不是“proguard-android-optimize.txt”。文件中甚至说dex自己做了一些优化,不符合优化的proguard规则。
  • 我想继续使用 Proguard 优化。
  • 正如我所说,dex 无论如何都会进行一些优化。我建议您尝试使用未优化的 proguard 规则版本,如果它从那里产生正确的构建工作。 |||原来优化的规则里面有!field/*,你的规则是不是少了一个感叹号?
  • 尝试为 Gson 添加这个 proguard sn-p。 github.com/krschultz/android-proguard-snippets/blob/master/…
  • 由于proguard对类文件进行了混淆,你如何看待混淆后的代码?

标签: android proguard


【解决方案1】:

我试图混淆一个可序列化的类,但我没有得到你的问题。我已经使用了默认的proguard-android-optimize.txt和你的优化版本,一切都很好。

原班

public class TestSerializable implements Serializable {
    private static final long serialVersionUID = 1L;

    @SerializedName("myField")
    private boolean myFieldEnabled = true;

    public boolean isMyFieldEnabled() {
        return myFieldEnabled;
    }

    public void setMyFieldEnabled(boolean myFieldEnabled) {
        this.myFieldEnabled = myFieldEnabled;
    }
}

在proguard之后

public final class p implements Serializable
{
    @c(a="myField")
    private boolean a = true;

    public final boolean a()
    {
        return this.a;
    }

    public final void b()
    {
        this.a = false;
    }
}

我有三个建议

  • 尝试将-keep class * implements java.io.Serializable 添加到您的 proguard 文件中,看看会发生什么
  • 在您的代码中验证方法setMyFieldEnabled(false) 不是在每个new MyClass 之后立即调用,否则优化可以决定删除默认值
  • 查看混淆后的序列化类:myFieldEnabled 字段是公开的;所以它可以从任何地方访问。如果 proguard 将代码替换为类似于 ai a = new ai(); ai.myFieldEnabled = true; 的代码,请检查使用 MyClass 的混淆类

【讨论】:

    【解决方案2】:

    尝试为实现 Serializable 的类声明默认构造函数

    public class MyClass implements Serializable {
        private static final long serialVersionUID = 1L;
    
        @SerializedName("myField")
        private boolean myFieldEnabled;
    
        private MyClass() {
            myFieldEnabled = true; 
        }  
    
        public boolean isMyFieldEnabled() {
            return myFieldEnabled;
        }
    
        public void setMyFieldEnabled(boolean myFieldEnabled) {
            this.myFieldEnabled = myFieldEnabled;
        }
    

    对于带有 serailisable 的默认 ProGaurd 配置,请参阅 http://proguard.sourceforge.net/manual/examples.html#serializable

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-05
      • 2011-07-14
      • 2019-09-10
      • 2021-10-03
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      相关资源
      最近更新 更多