Relates :
|
|
Relates :
|
# Summary Allow trusted implementors, internal to the JDK, to lock down selected arrays in such a way that the JVM rejects all future writes to them. # Goals This JEP allows the Java Virtual Machine to treat specially-marked array instances as read-only. A so-called "frozen array" can have any type, length, or contents, but its elements can never be reassigned. Frozen arrays will support certain optimizations and safety techniques (such as constant folding and defensive copying) which ordinary mutable arrays cannot support. This is a private feature within HotSpot and the `java.base` module. It is intended for use in internal optimizations, and also as a primitive for implementing user-visible [frozen arrays][JDK-8261007]. [JDK-8261007]: <https://bugs.openjdk.java.net/browse/JDK-8261007> # Non-Goals This JEP proposes no changes to the Java programming language. Changes to the Java language specification to allow for the existence of frozen arrays are the subject of a separate follow-on JEP, [JDK-8261007][JDK-8261007]. Building of a full user model for frozen arrays is also deferred to that JEP. Because they cannot be mutated, frozen arrays are non-compliant with the Java language (until the language is adjusted to admit them), and must not be exposed from any standard API until suitable adjustments are made. Thus, this JEP changes no standard API points in a way that would expose frozen array objects. # Motivation This is a first step towards user-visible frozen arrays. Please see [JDK-8261007][JDK-8261007] for the full motivation. # Description Define three new secure methods in `jdk.internal.misc.Unsafe`: ``` /** * Returns true if the given object is a frozen array. * The reference must be non-null and to an array. */ public boolean isFrozenArray(Object array) ... /** * Freeze the given array object. * The reference must be non-null and to an array * created by {@code makeLarvalArray} and * which has not yet been frozen. * The returned object is the same as the input * array, which has been frozen, or perhaps a copy * with the same type and contents. * * The input array must not be used an any way * (whether loads, stores, re-freezing, or anything * else) after the call returns. User should * Operations on the returned object must proceed as * if it were a fresh copy of the input array, even if * (as is likely in many cases but not all) the JVM * manages to recycle the object identity of the input array. * * The user must not rely on the JVM to actually check these * restrictions, which is why this method is unsafe. * * JIT IR representations should treat the input and output * values as distinct names. */ public Object freezeLarvalArray(Object array) ... /** * Create a new array of the given class and length, * with all elements initialized to their default values. * This array must not made visible to other threads, * or synchronized on. It may be passed as an input * to {@code freezeLarvalArray}. * * The user must not rely on the JVM to actually check these * restrictions, which is why this method is unsafe. */ public Object makeLarvalArray(Class<?> arrayClass, int length) ... ``` This is a first step towards user-visible frozen arrays. Please see [JDK-8261007][JDK-8261007] for the full description of non-internal APIs and use cases. It seems best to add these methods to `Unsafe` for these reasons: - They are in fact unsafe in the presence of race conditions, since an array might have concurrent state changes which are inconsistent with one thread's intentions to lock down an array. - They are also unsafe because they can be applied to "uncooperative" arrays, causing possibly dangerous failures (denials of service) when the affected arrays are used later by other modules. - They need to be "held tightly" until a safer user model is rolled out. - Any current user of `Unsafe` is likely to be "peeking and poking" into arrays, and must therefore be upgraded to respect the immutability of frozen arrays. Putting these methods into a new restricted API would make it incrementally more difficult to find and fix affected `Unsafe` code. # Alternatives We could plow ahead and introduce frozen arrays in the language with a user model. This JEP proposes a more incremental approach, validating internal use cases and optimizations before rolling it out to users. The current workaround for lack of constant folding is an internal annotation called `@jdk.internal.vm.annotation.Stable`. (In fact, frozen arrays are likely to use some of the same JIT optimization techniques as stable arrays.) We could continue to rely on that feature, without frozen arrays. But that has two problems: First, stable arrays are null-hostile, which sometimes causes inconveniences for (internal) users. Second, stable arrays do not yet have a well-accepted safe user model (as frozen arrays are likely to) so that stable arrays might never roll out as a public featuure. This is a first step towards user-visible frozen arrays. Please see [JDK-8261007][JDK-8261007] for the full description of non-internal APIs and use cases. # Risks and Assumptions The extra checks on array stores require some careful optimizer work, analogous to null pointer removal. These might cause performance problems. We might fail to build a user model, and be prevented from making these arrays available to end users, thus limiting their benefit. # Dependencies and Future Work There are no dependencies on existing work. Some engineering of array store checks for Project Valhalla may cross-apply to the mutability store checks required by this JEP. This is a first step towards user-visible frozen arrays. Please see [JDK-8261007][JDK-8261007], which depends on the low-level internal primitives defined by this work.