5

在将 Dexguard 从 7.0.12 更新到 7.1.22 后,我在 Enum 开关上遇到了崩溃。

这只发生在 Dexguard 在我们的项目上运行时(我想这是由 Proguard 问题引起的)。

如果我使用硬编码值,则不会发生崩溃。

当然,我想避免使用硬编码值。

迷恋;撞车;崩溃

发生的崩溃如下

java.lang.NoClassDefFoundError: Failed resolution of: Lif;

这发生在声明的行上switch(type) {(见下文)

例子

应用程序崩溃的一些示例代码(假设 MyEnum 是一个 Enum 当然):

MyEnum type = MyEnum.SomeValue;

switch (type) {
    case SomeValue:
        // Do something
        Log.i("Tag", "Hello world!");
        break;
}

假设 的序数值MyEnum.SomeValue为 1。

如果我改变它case SomeValue:case 1:它会像预期的那样工作。

我尝试过的

我不知道为什么会发生这种崩溃。我试图添加这些 Proguard 规则。

-keep enum * { *; }
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

但这并不能解决问题。

更新

我刚刚检查了映射文件,我所有的枚举名称等都被保留了。现在我对正在发生的事情更加一无所知。

my.identifier.MyEnum -> my.identifier.MyEnum:
    my.identifier.MyEnum SomeValue -> SomeValue
    my.identifier.MyEnum[] $VALUES -> $VALUES
    6:6:my.identifier.MyEnum[] values() -> values
    6:6:my.identifier.MyEnum valueOf(java.lang.String) -> valueOf
    6:6:void <init>(java.lang.String,int) -> <init>
    6:7:void <clinit>() -> <clinit>

更新 2

刚看了一下输出。编译成这个。从堆栈跟踪来看,我想ifProguard 没有保留。这是在哪里定义的?我需要添加什么才能让 Proguard 保留这个?

switch(if.ˊ[var2.ordinal()]) {
    case 1:
        //some other code
        break;

更新 3

在中间代码中,这行代码如下所示:

switch(null.$SwitchMap$my$identifier$MyEnum[type.ordinal()]) {
    case 1:
        //some other code
        break;

它陈述的事实null.$困扰着我。这似乎不对。或者这是正常的吗?

更新 4

刚刚恢复到我们旧版本的 Dexguard 并删除了我添加的 Proguard 规则。

现在不再发生崩溃,尽管代码看起来仍然完全相同。(中间体和完全编译的代码)

更新 5

切换到 Dexguard 7.2,它完美无缺。

4

2 回答 2

1

switch 语句将创建一个合成内部类,其中包含一个将枚举字段的序数映射到大于 0 的整数的数组字段$SwitchMap$MyEnum。您需要确保该类和它的字段也被保留。

于 2016-04-22T08:44:06.980 回答
1

我遇到了同样的问题。当我反编译类时,我看到问号(在这种情况下???应该是 arg0)

public static cr a(String arg0)
  {
    switch (???)
    {
    case "caseOne": 
      ??? = a;
      break;
    case "caseTwo": 
      ??? = f;
      break;
    default: 
      ??? = null;
    }
    return (cr)???;
  }

如果您在内部重新分配参数,例如

arg0= arg0.toLowerCase();

然后 proguard 明白该放什么而不是问号

public static cr a(String paramString)
  {
    switch (paramString = paramString.toLowerCase())
    {
    case "caseOne": 
      paramString = a;
      break;
    case "caseTwo": 
      paramString = f;
于 2019-01-05T15:03:13.573 回答