Why is this an issue?
Java offers a built-in serialization mechanism for classes that implement the Serializable
interface. The developer can either rely on
Java’s default serialization and deserialization logic or implement custom methods for these tasks. The JVM will use methods such as
readObject
and writeObject
to execute custom behavior. This only works, however, if these methods match exactly the expected
signatures. If they do not, the JVM will fall back to the default logic, resulting in unexpected behavior at runtime, while the developer believes
that the default logic has been overidden.
This rule raises an issue if an implementation of writeObject
, readObject
, readObjectNoData
,
writeReplace
, or readResolve
has an incorrect access modifier, return type, or is not static when it should be (and
vice-versa).
How to fix it
Ensure that the serialization-related method’s signatures match exactly those required by the JVM.
Code examples
Noncompliant code example
public class Watermelon implements Serializable {
void writeObject(java.io.ObjectOutputStream out) // Noncompliant, "writeObject" needs to be private, which it is not here
throws IOException
{...}
static Object readResolve() throws ObjectStreamException // Noncompliant, "readResolve" should not be static
{...}
Watermelon writeReplace() throws ObjectStreamException // Noncompliant, "writeReplace" must return "java.lang.Object"
{...}
}
Compliant solution
public class Watermelon implements Serializable {
private void writeObject(java.io.ObjectOutputStream out) // Compliant, method declared as private
throws IOException
{...}
protected Object readResolve() throws ObjectStreamException // Compliant, method is not static
{...}
private Object writeReplace() throws ObjectStreamException // Compliant, method returns "java.lang.Object"
{...}
}
Resources