3

オブジェクトを逆シリアル化する必要がありますが、readObject を使用してオブジェクトを読み取っているときに、次のような例外が発生します。

Exception raised: java.lang.Enum; Incompatible class (SUID): 
java.lang.Enum: static final long serialVersionUID =0L; 
but expected java.lang.Enum: static final long serialVersionUID =0L;

コードは次のとおりです。

public static void restore3x(PersistentHistory h, DictManager dictManager) throws Exception{
        SharedPreferences prefs = tryToGuess(h.mContext);
        if (prefs == null) return;
        Log.e("shdd","Found history!");
        String history = prefs.getString("History", null);
        ObjectInputStream objIn = null;
        try {
            //prepare
            objIn = new ObjectInputStream(new ByteArrayInputStream(Base64.decode(history))) {
                @Override
                protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
                    ObjectStreamClass osc = super.readClassDescriptor();
                    if (osc.getName().contains("slovoed")) {
                        try {
                            Field f;
                            f = osc.getClass().getDeclaredField("svUID");
                            f.setAccessible(true);
                            Log.e("shdd","Setting serialVersionUID");
                            f.setLong(osc, serialVersionUID);
                            Log.e("shdd","Set ok");
                            f = osc.getClass().getDeclaredField("className");
                            f.setAccessible(true);
                            Log.e("shdd","Setting class name");
                            f.set(osc, WordItem.class.getName());
                            Log.e("shdd","Set ok");
                        } catch (Exception e) {
                        }
                    }
                    return osc;
                }
            };
            //add to DB
            Log.e("shdd","Getting items");
            Collection<WordItem3x> items = (Collection<WordItem3x>) objIn.readObject();
            Log.e("shdd","Got ok");
            if (items.isEmpty()) return;
            Log.e("shdd","List's not empty");
            long timeSeconds = System.currentTimeMillis()/1000;
            for (WordItem3x w : items) {
                if (w.getWord() == null || w.getWord().length() == 0 || w.getIndexList() == 0) continue;
                Log.e("shdd","Adding word");
                h.add(w.getWord(), w.getIndexList(), timeSeconds--);
            }
        } catch (Exception e) {
            Log.e("shdd","Exception raised: " + e.getMessage());
            throw e;
        } finally {
            try { if (objIn != null) objIn.close(); } catch (Exception e) {}
            //prefs.edit().remove("History").commit();
        }
    }

何が悪いのかわかりません。多分誰かがそのような例外を見たことがありますか?

WordItem3x readObject メソッドは次のとおりです。

private void readObject(java.io.ObjectInputStream in) throws IOException,
                ClassNotFoundException {
            Log.e("shdd", "Reading object");
            in.defaultReadObject();

            int val1 = in.readInt();
            int val2 = in.readInt();
            if (val1 != -1 && val2 != -1) {
                direction = new Direction(val1, val2);
            } else
                direction = null;

            val1 = in.readInt();
            if (val1 != -1)
                typeList = eWordListType.values()[val1];
            else
                typeList = null;
        }

しかし、私が見ることができるように、これまでに呼び出されたことはありません。

4

1 に答える 1

0

(注: シリアル化コードは示されておらず、WordItem3x の実装はほとんど省略されています)

コードに基づいて、私ができる最善の推測は、readClassDescriptorリフレクションを使用して serialVersionUID を変更するハックが、最終的に列挙型の serialVersionUID の変更につながるということです。Java 仕様から、すべての enum エントリ serialVersionUID は 0L である必要があります。ある時点で、列挙型を none 0L に変更したに違いありません。スローしたAOSPのコードブロックは次のとおりです。

// Check SUIDs, note all SUID for Enum is 0L
if (0L != classDesc.getSerialVersionUID() || 0L != superClass.getSerialVersionUID()) {
        throw new InvalidClassException(superClass.getName(),
                "Incompatible class (SUID): " + superClass + " but expected " + superClass);
}

serialVersionUID を変更する前に、オブジェクトの名前を出力してみてください

ObjectStreamClass osc = super.readClassDescriptor();
osc.getName(); // is this an enum????
于 2013-03-27T00:11:57.480 に答える