Index: src/main/java/java/io/ObjectOutputStream.java =================================================================== --- src/main/java/java/io/ObjectOutputStream.java (revision 601296) +++ src/main/java/java/io/ObjectOutputStream.java (working copy) @@ -38,6 +38,11 @@ ObjectStreamConstants { /* + * Mask to zero SC_BLOC_DATA bit. + */ + private static final byte NOT_SC_BLOCK_DATA = (byte) (SC_BLOCK_DATA ^ 0xFF); + + /* * How many nested levels to writeObject. We may not need this. */ private int nestedLevels; @@ -1531,12 +1536,13 @@ boolean externalizable = false; externalizable = ObjectStreamClass.isExternalizable(classDesc .forClass()); - if (protocolVersion != PROTOCOL_VERSION_1) { - // Change for 1.2. Objects can be saved in old format - // (PROTOCOL_VERSION_1) or in the 1.2 format (PROTOCOL_VERSION_2). - // Nested "if" check to optimize checking. Second check is more - // expensive. - if (externalizable) { + + if (externalizable) { + if (protocolVersion == PROTOCOL_VERSION_1) { + flags &= NOT_SC_BLOCK_DATA; + } else { + // Change for 1.2. Objects can be saved in old format + // (PROTOCOL_VERSION_1) or in the 1.2 format (PROTOCOL_VERSION_2). flags |= SC_BLOCK_DATA; } } Index: src/main/java/java/io/ObjectStreamClass.java =================================================================== --- src/main/java/java/io/ObjectStreamClass.java (revision 601296) +++ src/main/java/java/io/ObjectStreamClass.java (working copy) @@ -267,6 +267,7 @@ boolean externalizable = isExternalizable(cl); if (externalizable) { flags |= ObjectStreamConstants.SC_EXTERNALIZABLE; + flags |= ObjectStreamConstants.SC_BLOCK_DATA; // use protocol version 2 by default } else if (serializable) { flags |= ObjectStreamConstants.SC_SERIALIZABLE; } Index: src/test/api/common/tests/api/java/io/ObjectInputStreamTest.java =================================================================== --- src/test/api/common/tests/api/java/io/ObjectInputStreamTest.java (revision 601296) +++ src/test/api/common/tests/api/java/io/ObjectInputStreamTest.java (working copy) @@ -20,6 +20,7 @@ import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.Externalizable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -27,8 +28,10 @@ import java.io.InputStream; import java.io.InvalidObjectException; import java.io.NotActiveException; +import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectInputValidation; +import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.OutputStream; @@ -1036,6 +1039,57 @@ assertTrue(java.util.Arrays.equals(integers, testArray.array)); } + public static class TestExtObject implements Externalizable { + public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(10); + } + + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + in.readInt(); + } + } + + static class TestObjectOutputStream extends ObjectOutputStream { + private ObjectStreamClass[] objs; + private int pos = 0; + + public TestObjectOutputStream(OutputStream out, ObjectStreamClass[] objs) throws IOException { + super(out); + this.objs = objs; + } + + protected void writeClassDescriptor(ObjectStreamClass osc) throws IOException { + objs[pos++] = osc; } + } + + static class TestObjectInputStream extends ObjectInputStream { + private ObjectStreamClass[] objs; + private int pos = 0; + + public TestObjectInputStream(InputStream in, ObjectStreamClass[] objs) throws IOException { + super(in); + this.objs = objs; + } + + protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { + return (ObjectStreamClass) objs[pos++]; + } + } + + // Regression test for HARMONY-4996 + public void test_readObject_replacedClassDescriptor() throws Exception { + ObjectStreamClass[] objs = new ObjectStreamClass[1000]; + PipedOutputStream pout = new PipedOutputStream(); + PipedInputStream pin = new PipedInputStream(pout); + ObjectOutputStream oout = new TestObjectOutputStream(pout, objs); + oout.writeObject(new TestExtObject()); + oout.writeObject("test"); + oout.close(); + ObjectInputStream oin = new TestObjectInputStream(pin, objs); + oin.readObject(); + oin.readObject(); + } + /** * Sets up the fixture, for example, open a network connection. This method * is called before a test is executed.