Frozen objects?
Remi Forax
forax at univ-mlv.fr
Sat Dec 16 19:24:19 UTC 2023
Hello,
As part of Valhalla, the VM support for what you want to do already exists because we need something similar to be able to deserialize a value class.
jdk.internal.misc.Unsafe provides several methods: makePrivateBuffer(), put*() and finishPrivateBuffer() [1].
Compared to your interface Freezable, the method equivalent of the method freeze(), finishPrivateBuffer() needs to returns a value so the VM/JIT can separate the reference to a piece of memory which is mutable from the reference to the same piece of memory which is frozen.
regards,
Rémi
[1] [ https://github.com/openjdk/valhalla/blob/lworld/src/java.base/share/classes/jdk/internal/misc/Unsafe.java#L299 | https://github.com/openjdk/valhalla/blob/lworld/src/java.base/share/classes/jdk/internal/misc/Unsafe.java#L299 ]
> From: "Archie Cobbs" <archie.cobbs at gmail.com>
> To: "amber-dev" <amber-dev at openjdk.org>
> Sent: Saturday, December 16, 2023 6:32:59 PM
> Subject: Frozen objects?
> Caveat: I'm just trying to educate myself on what's been discussed in the past,
> not actually suggest a new language feature. I'm sure this kind of idea has
> been discussed before so feel free to point me at some previous thread, etc.
> In C we have 'const' which essentially means "the memory allocated to this thing
> is immutable". The nice thing about 'const' is that it can apply to an
> individual variable or field in a structure, or it can apply to an entire C
> structure or C array. In effect it applies to any contiguous memory region that
> can be named/identified at the language level.
> On the other hand, it's just a language fiction, i.e., it can always be defeated
> at runtime by casting (except for static constants).
> In Java we have 'final' which (in part) is like 'const' for fields and
> variables, but unlike C 'final' can't be applied to larger memory regions like
> entire objects or entire arrays.
> In C, 'const' can be applied "dynamically" in the sense I can cast foo to const
> foo. Of course, this is only enforced at the language level.
> Summary of differences between C 'const' and Java 'final':
> * Granularity:
> * C: Any contiguous memory region that has a language name/identification
> * Java: At most 64 bits at a time (*) and arrays are not included
> * Advantage: C
> *
> Enforcement:
> * C: Enforced only by the compiler (mostly)
> * Java: Enforced by the compiler and at runtime
> * Advantage: Java
> *
> Dynamic Application:
> * C: Yes
> * Java: No
> * Advantage: C
> (*) With records and value objects we are gradually moving towards the ability
> for larger things than an individual field to be 'const'. More generally, Java
> has slowly been glomming on some of the goodness from functional programming,
> including making it easier to declare and work with immutable data.
> This all begs the question: why not take this idea to its logical conclusion?
> And while we're at it, make the capability fully dynamic, instead of limiting
> when you can 'freeze' something construction time?
> In other words, add the ability to "freeze" an object or array. If 'x' is
> frozen, whatever 'x' directly references becomes no longer mutable.
> A rough sketch...
> Add new Freezable interface:
> public interface Freezable {
> boolean isFrozen();
> static boolean freeze(Freezable obj); // returns false if already frozen
> }
> Arrays automatically implement Freezable (just like they do Cloneable )
> What about the memory model? Ideally it would work as if written like this:
> public class Foo implements Freezable {
> private volatile frozen; // set to true by Freezable.freeze()
> void mutateFooContent(Runnable mutation) {
> if (this.frozen)
> throw new FrozenObjectException();
> else
> mutation.run();
> }
> }
> But there could be a better trade-off of performance vs. semantics.
> Other trade-offs...
> * (-) All mutations to a Freezable would require a new 'frozen' check (* see
> below)
> * (-) There would have to be a new bit allocated in the object header
> * (+) Eliminate zillions of JDK defensive array copies (things like
> String.toCharArray() )
> * (+) JIT optimizations for constant-folding, etc.
> * (+) GC optimizations
> * (*) Put frozen objects into a read-only region of memory to eliminate mutation
> checks
> * Optimize scanning of frozen references (since they never change)
> I'm curious how other people think this idea would or wouldn't make sense for
> Java & what's been decided in the past.
> Thanks,
> -Archie
> --
> Archie L. Cobbs
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20231216/d6662a12/attachment.htm>
More information about the amber-dev
mailing list