Summary
This change causes javac to omit the synthetic field that holds a reference to the enclosing instance of a serializable inner class, if the inner class doesn't capture any state from its enclosing instance. This change is a generalization of JDK-8271717 to serializable classes.
Problem
The motivation is similar to JDK-8271717, where the unnecessary references affect performance and can cause memory leaks.
Additionally, for Serializable
inner classes, this change prevents unnecessary serialization of the associated outer class.
Solution
Similar to JDK-8271717, the solution is for javac to track whether a particular this$0
field is used when translating a serializable inner class, and omit unused fields.
This change would not be applied to classes that declare a serialVersionUID
, since the presence of the this$
field would affect the default serialVersionUID
value.
For classes that declare serialVersionUID
and use default serialization:
If the class does not use this$
, and a form of the class that contains an unused reference to this$
is deserialized, the field will be ignored.
If the class does use this$
, and a form of the class that does not contain this$
is deserialized, default serialization will fill in null
for this$
This means that if an inner class that does not use this$
is serialized, and the class is later changed to use this$
and recompiled, and the fold form is deserialized, it will be possible to observe a null
value for this$
.
For classes that use custom serialization, it is possible to inspect the this$
field directly. This was the source of a JCK test failure involving a test that explicitly tried to extract this$
from the serialized stream.
Specification
The Java Object Serialization Specification mentions the existence of the this$
fields in a note that starts with "serialization of inner classes ... is strongly discouraged for several reasons".
The note goes on to say:
inner classes declared in non-static contexts contain implicit non-transient references to enclosing class instances
This language could be updated to say that the inner classes may contain implicit non-transient references to the enclosing instance, to give the implementation latitude to optimize away the enclosing instance.
The note also mentions that:
Synthetic fields generated by javac (or other JavaTM compilers) to implement inner classes are implementation dependent and may vary between compilers; differences in such fields can disrupt compatibility as well as result in conflicting default serialVersionUID values
This acknowledges that the field is an unspecified implementation detail that is subject to change. It could potentially clarify that one of the ways that the synthetic field could change is for the compiler to omit it from an inner class that doesn't reference its enclosing instance.
- csr of
-
JDK-8278178 Omit enclosing instance fields from serializable inner classes that don't use it
-
- Open
-