Summary
-------
Define `java.lang.invoke.MethodHandles.Lookup::ensureInitialized` as a replacement API for `sun.misc.Unsafe::ensureClassInitialized`
Problem
-------
Class initialization will happen as specified in JLS 12.4 and JVMS 5.5 that involves accessing its member.
An existing programmatic way to initialize a class is `Class::forName` but that requires to know the name of the class and a class loader that can find such class. This may not always be feasible for frameworks.
Solution
--------
Add `Lookup::ensureInitialized` method to initialize the given class if the lookup has the access to the class to be initialized.
`Class::ensureInitialized` was another option considered. It should be caller sensitive in order to ensure the caller has the proper access to this class. This alternative may not work for frameworks which have no access to user classes. It would have to fallback to `Class::forName` limited solution.
OTOH a framework can use `Lookup::privateLookupIn` to access a class in another module if the module authorizes it by opening the packages for it to access. Or a user can produce a less privileged lookup by `Lookup::dropLookupMode` and pass it to the framework.
Specification
-------------
Add the `ensureInitialized` method in `java.lang.invoke.MethodHandles.Lookup`:
```
/**
* Ensures that {@code targetClass} has been initialized. The class
* to be initialized must be {@linkplain #accessClass accessible}
* to this {@code Lookup} object. This method causes {@code targetClass}
* to be initialized if it has not been already initialized,
* as specified in JVMS {@jvms 5.5}.
*
* @param targetClass the class to be initialized
* @return {@code targetClass} that has been initialized
*
* @throws IllegalArgumentException if {@code targetClass} is a primitive type or {@code void}
* or array class
* @throws IllegalAccessException if {@code targetClass} is not
* {@linkplain #accessClass accessible} to this lookup
* @throws ExceptionInInitializerError if the class initialization provoked
* by this method fails
* @throws SecurityException if a security manager is present and it
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @since 15
* @jvms 5.5 Initialization
*/
public Class<?> ensureClassInitialized(Class<?> targetClass) throws IllegalAccessException {
```
Deprecate `sun.misc.Unsafe::ensureClassInitialized` and `sun.misc.Unsafe::shouldBeInitialized` method for removal.
````
@@ -710,7 +710,11 @@
* Ensures the given class has been initialized. This is often
* needed in conjunction with obtaining the static field base of a
* class.
+ *
+ * @deprecated Use the {@link java.lang.invoke.MethodHandles.Lookup#ensureInitialized(Class)}
+ * method instead.
*/
+ @Deprecated(since = "15", forRemoval = true)
@ForceInline
public void ensureClassInitialized(Class<?> c) {
theInternalUnsafe.ensureClassInitialized(c);
```
```
+ *
+ * @deprecated No replacement API for this method. As multiple threads
+ * may be trying to initialize the same class or interface at the same time.
+ * The only reliable result returned by this method is {@code false}
+ * indicating that the given class has been initialized. Instead, simply
+ * call {@link java.lang.invoke.MethodHandles.Lookup#ensureInitialized(Class)}
+ * that does nothing if the given class has already been initialized.
+ * This method is subject to removal in a future version of JDK.
+ *
* @return false only if a call to {@code ensureClassInitialized} would have no effect
+ *
*/
+ @Deprecated(since = "15", forRemoval = true)
@ForceInline
public boolean shouldBeInitialized(Class<?> c) {
```