[suggestion] no inline forwarding pointer for shallowly immutable objects

Piotr Tarsa piotr.tarsa at gmail.com
Sat May 15 12:29:06 UTC 2021


I'm not an expert in JVM internals, so it's more of a question than an

On https://wiki.openjdk.java.net/display/lilliput there are already some
ideas about removing identity hash code field for shallowly immutable
objects. The contents of the wiki are:
> We can also reduce the size of the header for certain kind of classes, by
example for a record, we know that the field are truly final so we can
avoid to compute the hashCode and use the fields to calculate the identity
hashCode the same way Valhalla does for the primitive classes.
> For a primitive class, when they are on the heap, again, we can avoid the
identity hashCode (and also the lock bits, but that's less interresting).

I think we can similarly remove forwarding pointers, at least for boxed
primitive objects, as there may be many copies of a single identity-less
shallowly immutable object and that won't break anything (there's no way to
differentiate between the copies anyway). That could potentially reduce the
header size of such boxed primitive object to just the 32-bits that are
needed for keeping compressed class pointer (and nothing else). Maybe the
age bits (used in generational GCs) are not really needed for certain types
of objects, e.g. primitive objects that contain no references? This way the
smallest data carriers on heap would have just 8 bytes size (e.g. boxed
byte, short, char, int, float).

I was thinking for a while that forwarding pointer would also be unneeded
(and without replacement) for other types of shallowly immutable objects,
i.e. records and also frozen arrays (if they get accepted, the draft JEPs
are: https://bugs.openjdk.java.net/browse/JDK-8261007
https://bugs.openjdk.java.net/browse/JDK-8261099 - BTW I think they should
be mentioned on the Lilliput wiki page), but then realized that they (can)
have identity, so it's required to know (using the forwarding pointer) the
true single identity of them (to compare addresses or lock on them for
example). However, how often identity is used? Maybe keeping the forwarding
pointers for such objects in lazily filled side tables would reduce overall
memory overhead while keeping performance overhead relatively low?
Accessing a frozen array shouldn't require (I think) using the forwarding
pointer as both copies (if GC make a copy) of frozen array are shallowly
identical anyway. Same goes for records as they are also (if I understand
correctly) guaranteed to be shallowly immutable.


More information about the lilliput-dev mailing list