Serialization Member Ignored In Record
ID |
java.record_ignored_serialization_members |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Code Smell |
Language |
Java |
Tags |
code-style, serialization |
Description
Reports a writeObject, readObject, readObjectNoData, writeExternal or readExternal
method, or a serialPersistentFields field, declared directly inside a record.
Only member names decide the match — the exact signature (visibility, parameter type,
throws clause, @Override) is not checked. Ordinary classes are out of scope: these
members are only ever ignored inside a record.
Rationale
A record is serialized and deserialized through its components and the canonical
constructor. None of the classic Serializable / Externalizable customization hooks are
consulted, regardless of whether the record declares one of those interfaces. A member using
one of the reserved names therefore looks like working serialization logic but never runs,
and the gap between what was written and what the JVM does surfaces only once the "custom"
behavior is actually needed.
record Shipment(String trackingId, int weightGrams) implements Serializable {
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0]; // never consulted
private void writeObject(ObjectOutputStream out) throws IOException {
... // never invoked
}
}
writeReplace and readResolve are the two hooks a record does honor — they substitute
the object written to, or reconstructed from, the stream — and are never reported.
Remediation
Delete the member, or move the logic to where it can actually run: a compact constructor
for validation/normalization on deserialization, or writeReplace / readResolve for
substituting the serialized representation.
record Shipment(String trackingId, int weightGrams) implements Serializable {
Shipment { // compact constructor runs on every
if (weightGrams < 0) { // construction path, including
throw new IllegalArgumentException("weightGrams"); // deserialization
}
}
}