Idea: guaranteed object-level immutability, like in JavaScript's Object.freeze()

Piotr Tarsa piotr.tarsa at gmail.com
Tue Sep 29 18:30:00 UTC 2020


Hi,

JavaScript has a function Object.freeze(object) which makes that single
object fully immutable. Additionally an once frozen object cannot be
unfrozen at all. Java could implement something like that - add
Object.freeze() method that would make an object forever fully shallowly
immutable. Any attempt of mutating a frozen object would result in an
exception. Any (reflection-based) changes to constness of class fields
would be ignored, because freezing is at object-level, not at class-level.
Freeze status could be stored in the object header.

I think such object freezing could potentially bring safety and performance
improvements, e.g.:
- frozen objects could help garbage collection efficiency. Since frozen
objects are guaranteed to be immutable forever, you can probably access and
copy them without memory barriers during concurrent compaction phase
without risking losing changes to objects' changes (since they are
prohibited).
- freezing objects could potentially make (implemented in future)
speculation on values more effective as you don't have to track fields
immutability separately if you have an object that is wholly frozen.
- freezing objects would reduce the amount of defensive copying, especially
if applied to arrays. Immutable collections libraries designed to reduce
programming errors tend not to trust input arrays provided by library users
(as they are always mutable now). Instead they copy the array to a private
copy. This makes e.g. methods that take varargs and returns an immutable
collection unnecessarily costly. An immutable collections library could
just check if the input array is frozen and then skip copying it.

There's a potential problem though: race conditions when reading an
object's immutability flag. To make that operation (reading the flag) cheap
and thread-safe we can make existing objects freeze at global safepoint
only (so only writing the flag would be expensive). Since reaching a global
safepoint is expensive, the Object.freeze method could take an array of
objects, requiring a single pause to mark multiple objects. Another
(better?) way to make freezing relatively cheap is to combine it with
cloning, so we could have a static method Object.frozenMemberwiseClone()
that would return a frozen object, but wouldn't require a safepoint.

Do you think freezing objects could make sense for Java?

Regards,
Piotr


More information about the discuss mailing list