Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/java.base/share/classes/java/io/ObjectOutputStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -1402,9 +1402,17 @@ private void writeRecordData(Object obj, ObjectStreamClass desc)
private void writeSerialData(Object obj, ObjectStreamClass desc)
throws IOException
{
// As per the serialization spec, the serializable object's list of classes
// (that is, the class it instantiates and its superclasses) is processed
// in superclass-to-subclass order, starting with the first class that
// implements Serializable.
ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
for (int i = 0; i < slots.length; i++) {
ObjectStreamClass slotDesc = slots[i].desc;
// Verify that each of these classes comply with the serialization spec.
// Specifically, if the class is a concrete value class, or it has strict
// initialization instance field(s) then throw InvalidClassException.
slotDesc.checkSerialize();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This call sounds a bit risky - I doubt this might change preexisting serialization behavior. Also I don't think this should come before hasWriteObjectMethod in particular, might break writeReplace delegation too.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct me if I'm wrong, but this check would run on-each-write? Seems like a check like that should be cached, as I'm concerned about perf regressions as well.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The checkDeserialize for the original class is already run on each write.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A compromise might be opening up an issue to improve this (both from a regression-perspective, and in the case for deserialize it would be a potential avenue for improving performance).

if (slotDesc.hasWriteObjectMethod()) {
PutFieldImpl oldPut = curPut;
curPut = null;
Expand Down
9 changes: 8 additions & 1 deletion src/java.base/share/classes/java/io/ObjectStreamClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,15 @@ private ObjectStreamClass(final Class<?> cl) {
isProxy = Proxy.isProxyClass(cl);
isEnum = Enum.class.isAssignableFrom(cl);
isRecord = cl.isRecord();
requiresDeserializer = cl.isValue() || ValueClass.hasStrictInstanceField(cl);
serializable = Serializable.class.isAssignableFrom(cl);
// Serialization specification states that if a class implements java.io.Serializable,
// then serialization/deserialization isn't allowed if that class is a concrete value class
// or if that class has strict initialization instance field(s).
// However, for some JDK classes we make a provision to bypass that restriction.
// Such classes are required to have a jdk.internal.value.Deserializer associated with it.
requiresDeserializer = serializable &&
(ValueClass.isConcreteValueClass(cl) || ValueClass.hasStrictInstanceField(cl));

externalizable = Externalizable.class.isAssignableFrom(cl);

Class<?> superCl = cl.getSuperclass();
Expand Down