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;
}

の序数値が 1 であると仮定しますMyEnum.SomeValue

に変更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

$SwitchMap$MyEnumswitch ステートメントは、enum フィールドの序数を 0 より大きい整数にマッピングする配列フィールドを持つ合成内部クラスを作成します。このクラスとそのフィールドも保持されていることを確認する必要があります。

于 2016-04-22T08:44:06.980 に答える