简体   繁体   中英

Strange exception during deserialization

I need to deserialize object but when I'm reading object using readObject i get such exception:

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;

Here's the code:

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

I have no idea what's wrong. Maybe someone has seen such exceptions?

Here's WordItem3x readObject method:

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

But as i can see it's not ever called.

(note: there is no serialization code shown, and the WordItem3x implementation is mostly omitted)

Based on the code, the best guess I can make is that hack in readClassDescriptor where you use reflection to modify the serialVersionUID eventually leads to the modification of an enum's serialVersionUID. From the java spec, all enum entry serialVersionUID should be 0L. I'll bet at some point you changed an enum to be none 0L. Here's the block of code in AOSP that threw:

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

Try printing out the object's name before you modify the serialVersionUID

ObjectStreamClass osc = super.readClassDescriptor();
osc.getName(); // is this an enum????

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM