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

© 2026 Xygeni. All rights reserved