mirror of
https://github.com/github/codeql.git
synced 2026-03-20 06:26:47 +01:00
Where possible update Java documentation links to Java 11. Additionally update some other links to use HTTPS.
77 lines
3.5 KiB
XML
77 lines
3.5 KiB
XML
<!DOCTYPE qhelp PUBLIC
|
|
"-//Semmle//qhelp//EN"
|
|
"qhelp.dtd">
|
|
<qhelp>
|
|
|
|
|
|
<overview>
|
|
<p>
|
|
If a serializable class is serialized using the default Java serialization mechanism,
|
|
each non-static, non-transient field in the class must also be serializable.
|
|
Otherwise, the class generates a <code>java.io.NotSerializableException</code> as its fields are written
|
|
out by <code>ObjectOutputStream.writeObject</code>.
|
|
</p>
|
|
|
|
<p>
|
|
As an exception, classes that define their own <code>readObject</code> and <code>writeObject</code>
|
|
methods can have fields that are not themselves serializable. The <code>readObject</code> and
|
|
<code>writeObject</code> methods are responsible for encoding any state in those fields that needs
|
|
to be serialized.
|
|
</p>
|
|
|
|
</overview>
|
|
<recommendation>
|
|
<p>
|
|
To avoid causing a <code>NotSerializableException</code>, do one of the following:</p>
|
|
<ul>
|
|
<li>
|
|
<strong>Mark the field as <code>transient</code> : </strong> Marking the field as <code>transient</code> makes the
|
|
serialization mechanism skip the field. Before doing this, make sure that the field is not really intended
|
|
to be part of the persistent state of the object.
|
|
</li>
|
|
<li>
|
|
<strong>Define custom <code>readObject</code> and <code>writeObject</code> methods for the <code>Serializable</code> class : </strong>
|
|
Explicitly defining the <code>readObject</code> and <code>writeObject</code> methods enables you to choose which fields
|
|
to read from, or write to, an object stream during serialization.
|
|
</li>
|
|
<li>
|
|
<strong>Make the type of the field <code>Serializable</code> : </strong> If the field is part of the object's persistent state and you wish
|
|
to use Java's default serialization mechanism, the type of the field must implement <code>Serializable</code>. When choosing this option,
|
|
make sure that you follow best practices for serialization.
|
|
</li>
|
|
</ul>
|
|
|
|
</recommendation>
|
|
<section title="Example 1">
|
|
<p>In the following example, <code>WrongPerformanceRecord</code> contains a field <code>factors</code>
|
|
that is not serializable but is in a serializable class. This causes a <code>java.io.NotSerializableException</code>
|
|
when the field is written out by <code>writeObject</code>. However, <code>PerformanceRecord</code>
|
|
contains a field <code>factors</code> that is marked as <code>transient</code>, so that the serialization
|
|
mechanism skips the field. This means that a correctly serialized record is output by <code>writeObject</code>.</p>
|
|
<sample src="NonSerializableField.java" />
|
|
|
|
</section>
|
|
<section title="Example 2">
|
|
<p>In this second example, <code>WrongPair</code> takes two generic parameters <code>L</code> and <code>R</code>.
|
|
The class itself is serializable, but users of this class are not forced to pass serializable objects to its
|
|
constructor, which could lead to problems during serialization. The solution is to set upper type bounds for the
|
|
parameters, to force the user to supply only serializable objects.
|
|
A similar example is the <code>WrongEvent</code> class, which takes a weakly typed <code>eventData</code> object.
|
|
A better solution is to force the user to supply an object whose class implements the <code>Serializable</code>
|
|
interface.</p>
|
|
<sample src="NonSerializableFieldTooGeneral.java" />
|
|
|
|
</section>
|
|
<references>
|
|
|
|
|
|
<li>
|
|
Java API Specification:
|
|
<a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/Serializable.html">Serializable</a>,
|
|
<a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/ObjectOutputStream.html">ObjectOutputStream</a>.
|
|
</li>
|
|
|
|
|
|
</references>
|
|
</qhelp>
|