From 25ed2965e7da9c28af0fb92aab44b9858187aeb5 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2013 12:46:35 -0500 Subject: [PATCH] ObjectInputStream: use private readObject() methods The specification of the Java deserialization demands that a private readObject(ObjectOutputStream) method is used -- if it exists. In that case, ObjectInputStream must not initialize the contents of the fields (called 'classdata[]' in the documentation) but offer that functionality via the defaultReadObject() method. Signed-off-by: Johannes Schindelin --- classpath/java/io/ObjectInputStream.java | 39 +++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/classpath/java/io/ObjectInputStream.java b/classpath/java/io/ObjectInputStream.java index 796d6745d9..64c36a1d63 100644 --- a/classpath/java/io/ObjectInputStream.java +++ b/classpath/java/io/ObjectInputStream.java @@ -32,12 +32,14 @@ import static java.io.ObjectOutputStream.SC_BLOCK_DATA; import static java.io.ObjectOutputStream.SC_SERIALIZABLE; import static java.io.ObjectOutputStream.SC_EXTERNALIZABLE; import static java.io.ObjectOutputStream.SC_ENUM; +import static java.io.ObjectOutputStream.getReadOrWriteMethod; import avian.VMClass; import java.util.HashMap; import java.lang.reflect.Array; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class ObjectInputStream extends InputStream implements DataInput { @@ -310,7 +312,7 @@ public class ObjectInputStream extends InputStream implements DataInput { } catch (Exception ignored) { } int flags = rawByte(); - if (flags != SC_SERIALIZABLE) { + if ((flags & ~(SC_SERIALIZABLE | SC_WRITE_METHOD)) != 0) { throw new UnsupportedOperationException("Cannot handle flags: 0x" + Integer.toHexString(flags)); } @@ -344,8 +346,22 @@ public class ObjectInputStream extends InputStream implements DataInput { try { Object o = makeInstance(clazz.vmClass); - for (Field field : fields) { - field(field, o); + boolean customized = (flags & SC_WRITE_METHOD) != 0; + Method readMethod = customized ? + getReadOrWriteMethod(o, "readObject") : null; + if (readMethod == null) { + if (customized) { + throw new IOException("Could not find required readObject method in " + + clazz); + } + defaultReadObject(o, fields); + } else { + current = o; + currentFields = fields; + readMethod.invoke(o, this); + current = null; + currentFields = null; + expectToken(TC_ENDBLOCKDATA); } return o; @@ -356,8 +372,23 @@ public class ObjectInputStream extends InputStream implements DataInput { } } + private Object current; + private Field[] currentFields; + public void defaultReadObject() throws IOException { - throw new UnsupportedOperationException(); + defaultReadObject(current, currentFields); + } + + private void defaultReadObject(Object o, Field[] fields) throws IOException { + try { + for (Field field : fields) { + field(field, o); + } + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new IOException(e); + } } private static native Object makeInstance(VMClass c);