将Dexguard从7.0.12更新到7.1.22后,我在Enum交换机上遇到崩溃。
只有当Dexguard在我们的项目上运行时才会发生这种情况(我认为这是由Proguard问题引起的)。
如果我使用硬编码值,则不会发生崩溃。
当然,我想避免使用硬编码值。
发生的崩溃是以下
java.lang.NoClassDefFoundError: Failed resolution of: Lif;
这发生在说明switch(type) {
(见下文)
应用程序崩溃的一些示例代码(假设MyEnum是一个Enum ofcourse):
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>
刚看了一下输出。它编译成了这个。
判断堆栈跟踪,我认为Proguard不会保留if
。
这定义在哪里?我需要添加什么来让Proguard保留这个?
switch(if.ˊ[var2.ordinal()]) {
case 1:
//some other code
break;
在代码行看起来像这样的中间体:
switch(null.$SwitchMap$my$identifier$MyEnum[type.ordinal()]) {
case 1:
//some other code
break;
它表明null.$
困扰我的事实。这似乎不对。或者这是正常的吗?
刚刚恢复到我们旧版本的Dexguard并删除了我添加的Proguard规则。
现在崩溃不再发生了,尽管代码看起来仍然完全一样。 (中间体和完全编译的代码)
切换到Dexguard 7.2,它完美无瑕。
答案 0 :(得分:1)
switch语句将创建一个合成内部类,其数组字段$SwitchMap$MyEnum
将枚举字段的序号映射到大于0的整数。您需要确保此类及其字段也被保留。
答案 1 :(得分: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;