8235521: Replacement API for Unsafe::ensureClassInitialized

Reviewed-by: alanb, chegar, psandoz
This commit is contained in:
Mandy Chung 2020-06-08 16:55:45 -07:00
parent 6fc6476da8
commit 71d646a160
22 changed files with 708 additions and 83 deletions

View File

@ -27,6 +27,7 @@ package java.lang.invoke;
import jdk.internal.access.JavaLangAccess; import jdk.internal.access.JavaLangAccess;
import jdk.internal.access.SharedSecrets; import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.Unsafe;
import jdk.internal.misc.VM; import jdk.internal.misc.VM;
import jdk.internal.module.IllegalAccessLogger; import jdk.internal.module.IllegalAccessLogger;
import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassReader;
@ -2243,7 +2244,8 @@ public class MethodHandles {
Class<?> lookupClass = lookup.lookupClass(); Class<?> lookupClass = lookup.lookupClass();
ClassLoader loader = lookupClass.getClassLoader(); ClassLoader loader = lookupClass.getClassLoader();
ProtectionDomain pd = (loader != null) ? lookup.lookupClassProtectionDomain() : null; ProtectionDomain pd = (loader != null) ? lookup.lookupClassProtectionDomain() : null;
Class<?> c = JLA.defineClass(loader, lookupClass, name, bytes, pd, initialize, classFlags, classData); Class<?> c = SharedSecrets.getJavaLangAccess()
.defineClass(loader, lookupClass, name, bytes, pd, initialize, classFlags, classData);
assert !isNestmate() || c.getNestHost() == lookupClass.getNestHost(); assert !isNestmate() || c.getNestHost() == lookupClass.getNestHost();
return c; return c;
} }
@ -2263,7 +2265,7 @@ public class MethodHandles {
private ProtectionDomain lookupClassProtectionDomain() { private ProtectionDomain lookupClassProtectionDomain() {
ProtectionDomain pd = cachedProtectionDomain; ProtectionDomain pd = cachedProtectionDomain;
if (pd == null) { if (pd == null) {
cachedProtectionDomain = pd = JLA.protectionDomain(lookupClass); cachedProtectionDomain = pd = SharedSecrets.getJavaLangAccess().protectionDomain(lookupClass);
} }
return pd; return pd;
} }
@ -2283,8 +2285,6 @@ public class MethodHandles {
*/ */
static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, null, UNCONDITIONAL); static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, null, UNCONDITIONAL);
static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
private static void checkUnprivilegedlookupClass(Class<?> lookupClass) { private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
String name = lookupClass.getName(); String name = lookupClass.getName();
if (name.startsWith("java.lang.invoke.")) if (name.startsWith("java.lang.invoke."))
@ -2586,6 +2586,43 @@ assertEquals("[x, y, z]", pb.command().toString());
return accessClass(targetClass); return accessClass(targetClass);
} }
/**
* 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<?> ensureInitialized(Class<?> targetClass) throws IllegalAccessException {
if (targetClass.isPrimitive())
throw new IllegalArgumentException(targetClass + " is a primitive class");
if (targetClass.isArray())
throw new IllegalArgumentException(targetClass + " is an array class");
if (!VerifyAccess.isClassAccessible(targetClass, lookupClass, prevLookupClass, allowedModes)) {
throw new MemberName(targetClass).makeAccessException("access violation", this);
}
checkSecurityManager(targetClass, null);
// ensure class initialization
Unsafe.getUnsafe().ensureClassInitialized(targetClass);
return targetClass;
}
/** /**
* Determines if a class can be accessed from the lookup context defined by * Determines if a class can be accessed from the lookup context defined by
* this {@code Lookup} object. The static initializer of the class is not run. * this {@code Lookup} object. The static initializer of the class is not run.

View File

@ -27,6 +27,7 @@ package jdk.internal.access;
import javax.crypto.SealedObject; import javax.crypto.SealedObject;
import java.io.ObjectInputFilter; import java.io.ObjectInputFilter;
import java.lang.invoke.MethodHandles;
import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.jar.JarFile; import java.util.jar.JarFile;
@ -37,7 +38,6 @@ import java.io.ObjectInputStream;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.security.ProtectionDomain; import java.security.ProtectionDomain;
import java.security.Signature; import java.security.Signature;
import jdk.internal.misc.Unsafe;
/** A repository of "shared secrets", which are a mechanism for /** A repository of "shared secrets", which are a mechanism for
calling implementation-private methods in another package without calling implementation-private methods in another package without
@ -49,7 +49,7 @@ import jdk.internal.misc.Unsafe;
for this purpose, namely the loss of compile-time checking. */ for this purpose, namely the loss of compile-time checking. */
public class SharedSecrets { public class SharedSecrets {
private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
private static JavaAWTAccess javaAWTAccess; private static JavaAWTAccess javaAWTAccess;
private static JavaAWTFontAccess javaAWTFontAccess; private static JavaAWTFontAccess javaAWTFontAccess;
private static JavaBeansAccess javaBeansAccess; private static JavaBeansAccess javaBeansAccess;
@ -81,7 +81,7 @@ public class SharedSecrets {
if (javaUtilJarAccess == null) { if (javaUtilJarAccess == null) {
// Ensure JarFile is initialized; we know that this class // Ensure JarFile is initialized; we know that this class
// provides the shared secret // provides the shared secret
unsafe.ensureClassInitialized(JarFile.class); ensureClassInitialized(JarFile.class);
} }
return javaUtilJarAccess; return javaUtilJarAccess;
} }
@ -105,8 +105,7 @@ public class SharedSecrets {
public static JavaLangInvokeAccess getJavaLangInvokeAccess() { public static JavaLangInvokeAccess getJavaLangInvokeAccess() {
if (javaLangInvokeAccess == null) { if (javaLangInvokeAccess == null) {
try { try {
Class<?> c = Class.forName("java.lang.invoke.MethodHandleImpl"); Class.forName("java.lang.invoke.MethodHandleImpl", true, null);
unsafe.ensureClassInitialized(c);
} catch (ClassNotFoundException e) {}; } catch (ClassNotFoundException e) {};
} }
return javaLangInvokeAccess; return javaLangInvokeAccess;
@ -118,7 +117,7 @@ public class SharedSecrets {
public static JavaLangModuleAccess getJavaLangModuleAccess() { public static JavaLangModuleAccess getJavaLangModuleAccess() {
if (javaLangModuleAccess == null) { if (javaLangModuleAccess == null) {
unsafe.ensureClassInitialized(ModuleDescriptor.class); ensureClassInitialized(ModuleDescriptor.class);
} }
return javaLangModuleAccess; return javaLangModuleAccess;
} }
@ -145,7 +144,7 @@ public class SharedSecrets {
public static JavaNetUriAccess getJavaNetUriAccess() { public static JavaNetUriAccess getJavaNetUriAccess() {
if (javaNetUriAccess == null) if (javaNetUriAccess == null)
unsafe.ensureClassInitialized(java.net.URI.class); ensureClassInitialized(java.net.URI.class);
return javaNetUriAccess; return javaNetUriAccess;
} }
@ -155,7 +154,7 @@ public class SharedSecrets {
public static JavaNetURLAccess getJavaNetURLAccess() { public static JavaNetURLAccess getJavaNetURLAccess() {
if (javaNetURLAccess == null) if (javaNetURLAccess == null)
unsafe.ensureClassInitialized(java.net.URL.class); ensureClassInitialized(java.net.URL.class);
return javaNetURLAccess; return javaNetURLAccess;
} }
@ -165,7 +164,7 @@ public class SharedSecrets {
public static JavaNetInetAddressAccess getJavaNetInetAddressAccess() { public static JavaNetInetAddressAccess getJavaNetInetAddressAccess() {
if (javaNetInetAddressAccess == null) if (javaNetInetAddressAccess == null)
unsafe.ensureClassInitialized(java.net.InetAddress.class); ensureClassInitialized(java.net.InetAddress.class);
return javaNetInetAddressAccess; return javaNetInetAddressAccess;
} }
@ -175,7 +174,7 @@ public class SharedSecrets {
public static JavaNetHttpCookieAccess getJavaNetHttpCookieAccess() { public static JavaNetHttpCookieAccess getJavaNetHttpCookieAccess() {
if (javaNetHttpCookieAccess == null) if (javaNetHttpCookieAccess == null)
unsafe.ensureClassInitialized(java.net.HttpCookie.class); ensureClassInitialized(java.net.HttpCookie.class);
return javaNetHttpCookieAccess; return javaNetHttpCookieAccess;
} }
@ -187,7 +186,7 @@ public class SharedSecrets {
if (javaNioAccess == null) { if (javaNioAccess == null) {
// Ensure java.nio.Buffer is initialized, which provides the // Ensure java.nio.Buffer is initialized, which provides the
// shared secret. // shared secret.
unsafe.ensureClassInitialized(java.nio.Buffer.class); ensureClassInitialized(java.nio.Buffer.class);
} }
return javaNioAccess; return javaNioAccess;
} }
@ -198,7 +197,7 @@ public class SharedSecrets {
public static JavaIOAccess getJavaIOAccess() { public static JavaIOAccess getJavaIOAccess() {
if (javaIOAccess == null) { if (javaIOAccess == null) {
unsafe.ensureClassInitialized(Console.class); ensureClassInitialized(Console.class);
} }
return javaIOAccess; return javaIOAccess;
} }
@ -209,7 +208,7 @@ public class SharedSecrets {
public static JavaIOFilePermissionAccess getJavaIOFilePermissionAccess() { public static JavaIOFilePermissionAccess getJavaIOFilePermissionAccess() {
if (javaIOFilePermissionAccess == null) if (javaIOFilePermissionAccess == null)
unsafe.ensureClassInitialized(FilePermission.class); ensureClassInitialized(FilePermission.class);
return javaIOFilePermissionAccess; return javaIOFilePermissionAccess;
} }
@ -220,7 +219,7 @@ public class SharedSecrets {
public static JavaIOFileDescriptorAccess getJavaIOFileDescriptorAccess() { public static JavaIOFileDescriptorAccess getJavaIOFileDescriptorAccess() {
if (javaIOFileDescriptorAccess == null) if (javaIOFileDescriptorAccess == null)
unsafe.ensureClassInitialized(FileDescriptor.class); ensureClassInitialized(FileDescriptor.class);
return javaIOFileDescriptorAccess; return javaIOFileDescriptorAccess;
} }
@ -231,14 +230,14 @@ public class SharedSecrets {
public static JavaSecurityAccess getJavaSecurityAccess() { public static JavaSecurityAccess getJavaSecurityAccess() {
if (javaSecurityAccess == null) { if (javaSecurityAccess == null) {
unsafe.ensureClassInitialized(ProtectionDomain.class); ensureClassInitialized(ProtectionDomain.class);
} }
return javaSecurityAccess; return javaSecurityAccess;
} }
public static JavaUtilZipFileAccess getJavaUtilZipFileAccess() { public static JavaUtilZipFileAccess getJavaUtilZipFileAccess() {
if (javaUtilZipFileAccess == null) if (javaUtilZipFileAccess == null)
unsafe.ensureClassInitialized(java.util.zip.ZipFile.class); ensureClassInitialized(java.util.zip.ZipFile.class);
return javaUtilZipFileAccess; return javaUtilZipFileAccess;
} }
@ -276,7 +275,7 @@ public class SharedSecrets {
public static JavaUtilResourceBundleAccess getJavaUtilResourceBundleAccess() { public static JavaUtilResourceBundleAccess getJavaUtilResourceBundleAccess() {
if (javaUtilResourceBundleAccess == null) if (javaUtilResourceBundleAccess == null)
unsafe.ensureClassInitialized(ResourceBundle.class); ensureClassInitialized(ResourceBundle.class);
return javaUtilResourceBundleAccess; return javaUtilResourceBundleAccess;
} }
@ -286,7 +285,7 @@ public class SharedSecrets {
public static JavaObjectInputStreamReadString getJavaObjectInputStreamReadString() { public static JavaObjectInputStreamReadString getJavaObjectInputStreamReadString() {
if (javaObjectInputStreamReadString == null) { if (javaObjectInputStreamReadString == null) {
unsafe.ensureClassInitialized(ObjectInputStream.class); ensureClassInitialized(ObjectInputStream.class);
} }
return javaObjectInputStreamReadString; return javaObjectInputStreamReadString;
} }
@ -297,7 +296,7 @@ public class SharedSecrets {
public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() { public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() {
if (javaObjectInputStreamAccess == null) { if (javaObjectInputStreamAccess == null) {
unsafe.ensureClassInitialized(ObjectInputStream.class); ensureClassInitialized(ObjectInputStream.class);
} }
return javaObjectInputStreamAccess; return javaObjectInputStreamAccess;
} }
@ -308,7 +307,7 @@ public class SharedSecrets {
public static JavaObjectInputFilterAccess getJavaObjectInputFilterAccess() { public static JavaObjectInputFilterAccess getJavaObjectInputFilterAccess() {
if (javaObjectInputFilterAccess == null) { if (javaObjectInputFilterAccess == null) {
unsafe.ensureClassInitialized(ObjectInputFilter.Config.class); ensureClassInitialized(ObjectInputFilter.Config.class);
} }
return javaObjectInputFilterAccess; return javaObjectInputFilterAccess;
} }
@ -323,7 +322,7 @@ public class SharedSecrets {
public static JavaIORandomAccessFileAccess getJavaIORandomAccessFileAccess() { public static JavaIORandomAccessFileAccess getJavaIORandomAccessFileAccess() {
if (javaIORandomAccessFileAccess == null) { if (javaIORandomAccessFileAccess == null) {
unsafe.ensureClassInitialized(RandomAccessFile.class); ensureClassInitialized(RandomAccessFile.class);
} }
return javaIORandomAccessFileAccess; return javaIORandomAccessFileAccess;
} }
@ -334,7 +333,7 @@ public class SharedSecrets {
public static JavaSecuritySignatureAccess getJavaSecuritySignatureAccess() { public static JavaSecuritySignatureAccess getJavaSecuritySignatureAccess() {
if (javaSecuritySignatureAccess == null) { if (javaSecuritySignatureAccess == null) {
unsafe.ensureClassInitialized(Signature.class); ensureClassInitialized(Signature.class);
} }
return javaSecuritySignatureAccess; return javaSecuritySignatureAccess;
} }
@ -345,8 +344,14 @@ public class SharedSecrets {
public static JavaxCryptoSealedObjectAccess getJavaxCryptoSealedObjectAccess() { public static JavaxCryptoSealedObjectAccess getJavaxCryptoSealedObjectAccess() {
if (javaxCryptoSealedObjectAccess == null) { if (javaxCryptoSealedObjectAccess == null) {
unsafe.ensureClassInitialized(SealedObject.class); ensureClassInitialized(SealedObject.class);
} }
return javaxCryptoSealedObjectAccess; return javaxCryptoSealedObjectAccess;
} }
private static void ensureClassInitialized(Class<?> c) {
try {
MethodHandles.lookup().ensureInitialized(c);
} catch (IllegalAccessException e) {}
}
} }

View File

@ -25,8 +25,6 @@
package sun.awt; package sun.awt;
import jdk.internal.misc.Unsafe;
import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleContext;
import java.awt.*; import java.awt.*;
import java.awt.event.FocusEvent.Cause; import java.awt.event.FocusEvent.Cause;
@ -34,7 +32,6 @@ import java.awt.dnd.DragSourceContext;
import java.awt.dnd.DropTargetContext; import java.awt.dnd.DropTargetContext;
import java.awt.dnd.peer.DragSourceContextPeer; import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.dnd.peer.DropTargetContextPeer; import java.awt.dnd.peer.DropTargetContextPeer;
import java.awt.event.AWTEventListener;
import java.awt.event.InputEvent; import java.awt.event.InputEvent;
import java.awt.event.InvocationEvent; import java.awt.event.InvocationEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
@ -44,6 +41,7 @@ import java.awt.image.BufferStrategy;
import java.awt.peer.ComponentPeer; import java.awt.peer.ComponentPeer;
import java.awt.peer.MenuComponentPeer; import java.awt.peer.MenuComponentPeer;
import java.lang.invoke.MethodHandles;;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.security.AccessControlContext; import java.security.AccessControlContext;
@ -61,8 +59,6 @@ import javax.accessibility.AccessibleBundle;
*/ */
public final class AWTAccessor { public final class AWTAccessor {
private static final Unsafe unsafe = Unsafe.getUnsafe();
/* /*
* We don't need any objects of this class. * We don't need any objects of this class.
* It's rather a collection of static methods * It's rather a collection of static methods
@ -877,7 +873,7 @@ public final class AWTAccessor {
*/ */
public static ComponentAccessor getComponentAccessor() { public static ComponentAccessor getComponentAccessor() {
if (componentAccessor == null) { if (componentAccessor == null) {
unsafe.ensureClassInitialized(Component.class); ensureClassInitialized(Component.class);
} }
return componentAccessor; return componentAccessor;
@ -895,7 +891,7 @@ public final class AWTAccessor {
*/ */
public static ContainerAccessor getContainerAccessor() { public static ContainerAccessor getContainerAccessor() {
if (containerAccessor == null) { if (containerAccessor == null) {
unsafe.ensureClassInitialized(Container.class); ensureClassInitialized(Container.class);
} }
return containerAccessor; return containerAccessor;
@ -913,7 +909,7 @@ public final class AWTAccessor {
*/ */
public static WindowAccessor getWindowAccessor() { public static WindowAccessor getWindowAccessor() {
if (windowAccessor == null) { if (windowAccessor == null) {
unsafe.ensureClassInitialized(Window.class); ensureClassInitialized(Window.class);
} }
return windowAccessor; return windowAccessor;
} }
@ -930,7 +926,7 @@ public final class AWTAccessor {
*/ */
public static AWTEventAccessor getAWTEventAccessor() { public static AWTEventAccessor getAWTEventAccessor() {
if (awtEventAccessor == null) { if (awtEventAccessor == null) {
unsafe.ensureClassInitialized(AWTEvent.class); ensureClassInitialized(AWTEvent.class);
} }
return awtEventAccessor; return awtEventAccessor;
} }
@ -947,7 +943,7 @@ public final class AWTAccessor {
*/ */
public static InputEventAccessor getInputEventAccessor() { public static InputEventAccessor getInputEventAccessor() {
if (inputEventAccessor == null) { if (inputEventAccessor == null) {
unsafe.ensureClassInitialized(InputEvent.class); ensureClassInitialized(InputEvent.class);
} }
return inputEventAccessor; return inputEventAccessor;
} }
@ -964,7 +960,7 @@ public final class AWTAccessor {
*/ */
public static MouseEventAccessor getMouseEventAccessor() { public static MouseEventAccessor getMouseEventAccessor() {
if (mouseEventAccessor == null) { if (mouseEventAccessor == null) {
unsafe.ensureClassInitialized(MouseEvent.class); ensureClassInitialized(MouseEvent.class);
} }
return mouseEventAccessor; return mouseEventAccessor;
} }
@ -981,7 +977,7 @@ public final class AWTAccessor {
*/ */
public static FrameAccessor getFrameAccessor() { public static FrameAccessor getFrameAccessor() {
if (frameAccessor == null) { if (frameAccessor == null) {
unsafe.ensureClassInitialized(Frame.class); ensureClassInitialized(Frame.class);
} }
return frameAccessor; return frameAccessor;
} }
@ -998,7 +994,7 @@ public final class AWTAccessor {
*/ */
public static KeyboardFocusManagerAccessor getKeyboardFocusManagerAccessor() { public static KeyboardFocusManagerAccessor getKeyboardFocusManagerAccessor() {
if (kfmAccessor == null) { if (kfmAccessor == null) {
unsafe.ensureClassInitialized(KeyboardFocusManager.class); ensureClassInitialized(KeyboardFocusManager.class);
} }
return kfmAccessor; return kfmAccessor;
} }
@ -1015,7 +1011,7 @@ public final class AWTAccessor {
*/ */
public static MenuComponentAccessor getMenuComponentAccessor() { public static MenuComponentAccessor getMenuComponentAccessor() {
if (menuComponentAccessor == null) { if (menuComponentAccessor == null) {
unsafe.ensureClassInitialized(MenuComponent.class); ensureClassInitialized(MenuComponent.class);
} }
return menuComponentAccessor; return menuComponentAccessor;
} }
@ -1032,7 +1028,7 @@ public final class AWTAccessor {
*/ */
public static EventQueueAccessor getEventQueueAccessor() { public static EventQueueAccessor getEventQueueAccessor() {
if (eventQueueAccessor == null) { if (eventQueueAccessor == null) {
unsafe.ensureClassInitialized(EventQueue.class); ensureClassInitialized(EventQueue.class);
} }
return eventQueueAccessor; return eventQueueAccessor;
} }
@ -1049,7 +1045,7 @@ public final class AWTAccessor {
*/ */
public static PopupMenuAccessor getPopupMenuAccessor() { public static PopupMenuAccessor getPopupMenuAccessor() {
if (popupMenuAccessor == null) { if (popupMenuAccessor == null) {
unsafe.ensureClassInitialized(PopupMenu.class); ensureClassInitialized(PopupMenu.class);
} }
return popupMenuAccessor; return popupMenuAccessor;
} }
@ -1066,7 +1062,7 @@ public final class AWTAccessor {
*/ */
public static FileDialogAccessor getFileDialogAccessor() { public static FileDialogAccessor getFileDialogAccessor() {
if (fileDialogAccessor == null) { if (fileDialogAccessor == null) {
unsafe.ensureClassInitialized(FileDialog.class); ensureClassInitialized(FileDialog.class);
} }
return fileDialogAccessor; return fileDialogAccessor;
} }
@ -1084,7 +1080,7 @@ public final class AWTAccessor {
*/ */
public static ScrollPaneAdjustableAccessor getScrollPaneAdjustableAccessor() { public static ScrollPaneAdjustableAccessor getScrollPaneAdjustableAccessor() {
if (scrollPaneAdjustableAccessor == null) { if (scrollPaneAdjustableAccessor == null) {
unsafe.ensureClassInitialized(ScrollPaneAdjustable.class); ensureClassInitialized(ScrollPaneAdjustable.class);
} }
return scrollPaneAdjustableAccessor; return scrollPaneAdjustableAccessor;
} }
@ -1101,7 +1097,7 @@ public final class AWTAccessor {
*/ */
public static CheckboxMenuItemAccessor getCheckboxMenuItemAccessor() { public static CheckboxMenuItemAccessor getCheckboxMenuItemAccessor() {
if (checkboxMenuItemAccessor == null) { if (checkboxMenuItemAccessor == null) {
unsafe.ensureClassInitialized(CheckboxMenuItemAccessor.class); ensureClassInitialized(CheckboxMenuItemAccessor.class);
} }
return checkboxMenuItemAccessor; return checkboxMenuItemAccessor;
} }
@ -1118,7 +1114,7 @@ public final class AWTAccessor {
*/ */
public static CursorAccessor getCursorAccessor() { public static CursorAccessor getCursorAccessor() {
if (cursorAccessor == null) { if (cursorAccessor == null) {
unsafe.ensureClassInitialized(CursorAccessor.class); ensureClassInitialized(CursorAccessor.class);
} }
return cursorAccessor; return cursorAccessor;
} }
@ -1135,7 +1131,7 @@ public final class AWTAccessor {
*/ */
public static MenuBarAccessor getMenuBarAccessor() { public static MenuBarAccessor getMenuBarAccessor() {
if (menuBarAccessor == null) { if (menuBarAccessor == null) {
unsafe.ensureClassInitialized(MenuBarAccessor.class); ensureClassInitialized(MenuBarAccessor.class);
} }
return menuBarAccessor; return menuBarAccessor;
} }
@ -1152,7 +1148,7 @@ public final class AWTAccessor {
*/ */
public static MenuItemAccessor getMenuItemAccessor() { public static MenuItemAccessor getMenuItemAccessor() {
if (menuItemAccessor == null) { if (menuItemAccessor == null) {
unsafe.ensureClassInitialized(MenuItemAccessor.class); ensureClassInitialized(MenuItemAccessor.class);
} }
return menuItemAccessor; return menuItemAccessor;
} }
@ -1169,7 +1165,7 @@ public final class AWTAccessor {
*/ */
public static MenuAccessor getMenuAccessor() { public static MenuAccessor getMenuAccessor() {
if (menuAccessor == null) { if (menuAccessor == null) {
unsafe.ensureClassInitialized(MenuAccessor.class); ensureClassInitialized(MenuAccessor.class);
} }
return menuAccessor; return menuAccessor;
} }
@ -1186,7 +1182,7 @@ public final class AWTAccessor {
*/ */
public static KeyEventAccessor getKeyEventAccessor() { public static KeyEventAccessor getKeyEventAccessor() {
if (keyEventAccessor == null) { if (keyEventAccessor == null) {
unsafe.ensureClassInitialized(KeyEventAccessor.class); ensureClassInitialized(KeyEventAccessor.class);
} }
return keyEventAccessor; return keyEventAccessor;
} }
@ -1203,7 +1199,7 @@ public final class AWTAccessor {
*/ */
public static ClientPropertyKeyAccessor getClientPropertyKeyAccessor() { public static ClientPropertyKeyAccessor getClientPropertyKeyAccessor() {
if (clientPropertyKeyAccessor == null) { if (clientPropertyKeyAccessor == null) {
unsafe.ensureClassInitialized(ClientPropertyKeyAccessor.class); ensureClassInitialized(ClientPropertyKeyAccessor.class);
} }
return clientPropertyKeyAccessor; return clientPropertyKeyAccessor;
} }
@ -1220,7 +1216,7 @@ public final class AWTAccessor {
*/ */
public static SystemTrayAccessor getSystemTrayAccessor() { public static SystemTrayAccessor getSystemTrayAccessor() {
if (systemTrayAccessor == null) { if (systemTrayAccessor == null) {
unsafe.ensureClassInitialized(SystemTrayAccessor.class); ensureClassInitialized(SystemTrayAccessor.class);
} }
return systemTrayAccessor; return systemTrayAccessor;
} }
@ -1237,7 +1233,7 @@ public final class AWTAccessor {
*/ */
public static TrayIconAccessor getTrayIconAccessor() { public static TrayIconAccessor getTrayIconAccessor() {
if (trayIconAccessor == null) { if (trayIconAccessor == null) {
unsafe.ensureClassInitialized(TrayIconAccessor.class); ensureClassInitialized(TrayIconAccessor.class);
} }
return trayIconAccessor; return trayIconAccessor;
} }
@ -1254,7 +1250,7 @@ public final class AWTAccessor {
*/ */
public static DefaultKeyboardFocusManagerAccessor getDefaultKeyboardFocusManagerAccessor() { public static DefaultKeyboardFocusManagerAccessor getDefaultKeyboardFocusManagerAccessor() {
if (defaultKeyboardFocusManagerAccessor == null) { if (defaultKeyboardFocusManagerAccessor == null) {
unsafe.ensureClassInitialized(DefaultKeyboardFocusManagerAccessor.class); ensureClassInitialized(DefaultKeyboardFocusManagerAccessor.class);
} }
return defaultKeyboardFocusManagerAccessor; return defaultKeyboardFocusManagerAccessor;
} }
@ -1271,7 +1267,7 @@ public final class AWTAccessor {
public static SequencedEventAccessor getSequencedEventAccessor() { public static SequencedEventAccessor getSequencedEventAccessor() {
if (sequencedEventAccessor == null) { if (sequencedEventAccessor == null) {
try { try {
unsafe.ensureClassInitialized( ensureClassInitialized(
Class.forName("java.awt.SequencedEvent")); Class.forName("java.awt.SequencedEvent"));
} catch (ClassNotFoundException ignore) { } catch (ClassNotFoundException ignore) {
} }
@ -1291,7 +1287,7 @@ public final class AWTAccessor {
*/ */
public static ToolkitAccessor getToolkitAccessor() { public static ToolkitAccessor getToolkitAccessor() {
if (toolkitAccessor == null) { if (toolkitAccessor == null) {
unsafe.ensureClassInitialized(Toolkit.class); ensureClassInitialized(Toolkit.class);
} }
return toolkitAccessor; return toolkitAccessor;
@ -1316,7 +1312,7 @@ public final class AWTAccessor {
*/ */
public static SystemColorAccessor getSystemColorAccessor() { public static SystemColorAccessor getSystemColorAccessor() {
if (systemColorAccessor == null) { if (systemColorAccessor == null) {
unsafe.ensureClassInitialized(SystemColor.class); ensureClassInitialized(SystemColor.class);
} }
return systemColorAccessor; return systemColorAccessor;
@ -1334,7 +1330,7 @@ public final class AWTAccessor {
*/ */
public static AccessibleContextAccessor getAccessibleContextAccessor() { public static AccessibleContextAccessor getAccessibleContextAccessor() {
if (accessibleContextAccessor == null) { if (accessibleContextAccessor == null) {
unsafe.ensureClassInitialized(AccessibleContext.class); ensureClassInitialized(AccessibleContext.class);
} }
return accessibleContextAccessor; return accessibleContextAccessor;
} }
@ -1351,7 +1347,7 @@ public final class AWTAccessor {
*/ */
public static AccessibleBundleAccessor getAccessibleBundleAccessor() { public static AccessibleBundleAccessor getAccessibleBundleAccessor() {
if (accessibleBundleAccessor == null) { if (accessibleBundleAccessor == null) {
unsafe.ensureClassInitialized(AccessibleBundle.class); ensureClassInitialized(AccessibleBundle.class);
} }
return accessibleBundleAccessor; return accessibleBundleAccessor;
} }
@ -1368,7 +1364,7 @@ public final class AWTAccessor {
*/ */
public static DragSourceContextAccessor getDragSourceContextAccessor() { public static DragSourceContextAccessor getDragSourceContextAccessor() {
if (dragSourceContextAccessor == null) { if (dragSourceContextAccessor == null) {
unsafe.ensureClassInitialized(DragSourceContext.class); ensureClassInitialized(DragSourceContext.class);
} }
return dragSourceContextAccessor; return dragSourceContextAccessor;
} }
@ -1385,7 +1381,7 @@ public final class AWTAccessor {
*/ */
public static DropTargetContextAccessor getDropTargetContextAccessor() { public static DropTargetContextAccessor getDropTargetContextAccessor() {
if (dropTargetContextAccessor == null) { if (dropTargetContextAccessor == null) {
unsafe.ensureClassInitialized(DropTargetContext.class); ensureClassInitialized(DropTargetContext.class);
} }
return dropTargetContextAccessor; return dropTargetContextAccessor;
} }
@ -1397,4 +1393,9 @@ public final class AWTAccessor {
AWTAccessor.dropTargetContextAccessor = accessor; AWTAccessor.dropTargetContextAccessor = accessor;
} }
private static void ensureClassInitialized(Class<?> c) {
try {
MethodHandles.lookup().ensureInitialized(c);
} catch (IllegalAccessException e) {}
}
} }

View File

@ -25,9 +25,8 @@
package sun.swing; package sun.swing;
import jdk.internal.misc.Unsafe;
import java.awt.*; import java.awt.*;
import java.lang.invoke.MethodHandles;
import javax.swing.*; import javax.swing.*;
import javax.swing.text.JTextComponent; import javax.swing.text.JTextComponent;
@ -40,8 +39,6 @@ import javax.swing.text.JTextComponent;
* for another example. * for another example.
*/ */
public final class SwingAccessor { public final class SwingAccessor {
private static final Unsafe unsafe = Unsafe.getUnsafe();
/** /**
* We don't need any objects of this class. * We don't need any objects of this class.
* It's rather a collection of static methods * It's rather a collection of static methods
@ -142,7 +139,7 @@ public final class SwingAccessor {
*/ */
public static JComponentAccessor getJComponentAccessor() { public static JComponentAccessor getJComponentAccessor() {
if (jComponentAccessor == null) { if (jComponentAccessor == null) {
unsafe.ensureClassInitialized(JComponent.class); ensureClassInitialized(JComponent.class);
} }
return jComponentAccessor; return jComponentAccessor;
@ -165,7 +162,7 @@ public final class SwingAccessor {
*/ */
public static JTextComponentAccessor getJTextComponentAccessor() { public static JTextComponentAccessor getJTextComponentAccessor() {
if (jtextComponentAccessor == null) { if (jtextComponentAccessor == null) {
unsafe.ensureClassInitialized(JTextComponent.class); ensureClassInitialized(JTextComponent.class);
} }
return jtextComponentAccessor; return jtextComponentAccessor;
@ -188,7 +185,7 @@ public final class SwingAccessor {
*/ */
public static JLightweightFrameAccessor getJLightweightFrameAccessor() { public static JLightweightFrameAccessor getJLightweightFrameAccessor() {
if (jLightweightFrameAccessor == null) { if (jLightweightFrameAccessor == null) {
unsafe.ensureClassInitialized(JLightweightFrame.class); ensureClassInitialized(JLightweightFrame.class);
} }
return jLightweightFrameAccessor; return jLightweightFrameAccessor;
} }
@ -210,7 +207,7 @@ public final class SwingAccessor {
*/ */
public static UIDefaultsAccessor getUIDefaultsAccessor() { public static UIDefaultsAccessor getUIDefaultsAccessor() {
if (uiDefaultsAccessor == null) { if (uiDefaultsAccessor == null) {
unsafe.ensureClassInitialized(UIDefaults.class); ensureClassInitialized(UIDefaults.class);
} }
return uiDefaultsAccessor; return uiDefaultsAccessor;
} }
@ -232,7 +229,7 @@ public final class SwingAccessor {
*/ */
public static RepaintManagerAccessor getRepaintManagerAccessor() { public static RepaintManagerAccessor getRepaintManagerAccessor() {
if (repaintManagerAccessor == null) { if (repaintManagerAccessor == null) {
unsafe.ensureClassInitialized(RepaintManager.class); ensureClassInitialized(RepaintManager.class);
} }
return repaintManagerAccessor; return repaintManagerAccessor;
} }
@ -247,7 +244,7 @@ public final class SwingAccessor {
*/ */
public static PopupFactoryAccessor getPopupFactoryAccessor() { public static PopupFactoryAccessor getPopupFactoryAccessor() {
if (popupFactoryAccessor == null) { if (popupFactoryAccessor == null) {
unsafe.ensureClassInitialized(PopupFactory.class); ensureClassInitialized(PopupFactory.class);
} }
return popupFactoryAccessor; return popupFactoryAccessor;
} }
@ -269,7 +266,7 @@ public final class SwingAccessor {
*/ */
public static KeyStrokeAccessor getKeyStrokeAccessor() { public static KeyStrokeAccessor getKeyStrokeAccessor() {
if (keyStrokeAccessor == null) { if (keyStrokeAccessor == null) {
unsafe.ensureClassInitialized(KeyStroke.class); ensureClassInitialized(KeyStroke.class);
} }
return keyStrokeAccessor; return keyStrokeAccessor;
} }
@ -280,4 +277,10 @@ public final class SwingAccessor {
public static void setKeyStrokeAccessor(KeyStrokeAccessor accessor) { public static void setKeyStrokeAccessor(KeyStrokeAccessor accessor) {
SwingAccessor.keyStrokeAccessor = accessor; SwingAccessor.keyStrokeAccessor = accessor;
} }
private static void ensureClassInitialized(Class<?> c) {
try {
MethodHandles.lookup().ensureInitialized(c);
} catch (IllegalAccessException e) {}
}
} }

View File

@ -25,6 +25,7 @@
package sun.management; package sun.management;
import java.lang.invoke.MethodHandles;
import java.lang.management.*; import java.lang.management.*;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -39,7 +40,6 @@ import java.security.AccessController;
import java.security.PrivilegedActionException; import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.VM; import jdk.internal.misc.VM;
import jdk.internal.misc.VM.BufferPool; import jdk.internal.misc.VM.BufferPool;
@ -63,7 +63,9 @@ public class ManagementFactoryHelper {
static { static {
// make sure that the management lib is loaded within // make sure that the management lib is loaded within
// java.lang.management.ManagementFactory // java.lang.management.ManagementFactory
jdk.internal.misc.Unsafe.getUnsafe().ensureClassInitialized(ManagementFactory.class); try {
MethodHandles.lookup().ensureInitialized(ManagementFactory.class);
} catch (IllegalAccessException e) {}
} }
private static final VMManagement jvm = new VMManagementImpl(); private static final VMManagement jvm = new VMManagementImpl();

View File

@ -25,11 +25,10 @@
package sun.security.krb5; package sun.security.krb5;
import java.lang.invoke.MethodHandles;
import javax.security.auth.kerberos.KeyTab; import javax.security.auth.kerberos.KeyTab;
import jdk.internal.misc.Unsafe;
public class KerberosSecrets { public class KerberosSecrets {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static JavaxSecurityAuthKerberosAccess javaxSecurityAuthKerberosAccess; private static JavaxSecurityAuthKerberosAccess javaxSecurityAuthKerberosAccess;
public static void setJavaxSecurityAuthKerberosAccess public static void setJavaxSecurityAuthKerberosAccess
@ -39,8 +38,11 @@ public class KerberosSecrets {
public static JavaxSecurityAuthKerberosAccess public static JavaxSecurityAuthKerberosAccess
getJavaxSecurityAuthKerberosAccess() { getJavaxSecurityAuthKerberosAccess() {
if (javaxSecurityAuthKerberosAccess == null) if (javaxSecurityAuthKerberosAccess == null) {
unsafe.ensureClassInitialized(KeyTab.class); try {
MethodHandles.lookup().ensureInitialized(KeyTab.class);
} catch (IllegalAccessException e) {}
}
return javaxSecurityAuthKerberosAccess; return javaxSecurityAuthKerberosAccess;
} }
} }

View File

@ -33,6 +33,7 @@ import static org.graalvm.compiler.graph.Node.WithAllEdges;
import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe; import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
@ -133,6 +134,7 @@ public final class NodeClass<T> extends FieldIntrospection<T> {
public static <T> NodeClass<T> get(Class<T> clazz) { public static <T> NodeClass<T> get(Class<T> clazz) {
int numTries = 0; int numTries = 0;
while (true) { while (true) {
@SuppressWarnings("removal")
boolean shouldBeInitializedBefore = UNSAFE.shouldBeInitialized(clazz); boolean shouldBeInitializedBefore = UNSAFE.shouldBeInitialized(clazz);
NodeClass<T> result = getUnchecked(clazz); NodeClass<T> result = getUnchecked(clazz);
@ -146,13 +148,18 @@ public final class NodeClass<T> extends FieldIntrospection<T> {
* information without failing gates. * information without failing gates.
*/ */
numTries++; numTries++;
@SuppressWarnings("removal")
boolean shouldBeInitializedAfter = UNSAFE.shouldBeInitialized(clazz); boolean shouldBeInitializedAfter = UNSAFE.shouldBeInitialized(clazz);
String msg = "GR-9537 Reflective field access of TYPE field returned null. This is probably a bug in HotSpot class initialization. " + String msg = "GR-9537 Reflective field access of TYPE field returned null. This is probably a bug in HotSpot class initialization. " +
" clazz: " + clazz.getTypeName() + ", numTries: " + numTries + " clazz: " + clazz.getTypeName() + ", numTries: " + numTries +
", shouldBeInitializedBefore: " + shouldBeInitializedBefore + ", shouldBeInitializedAfter: " + shouldBeInitializedAfter; ", shouldBeInitializedBefore: " + shouldBeInitializedBefore + ", shouldBeInitializedAfter: " + shouldBeInitializedAfter;
if (numTries <= 100) { if (numTries <= 100) {
TTY.println(msg); TTY.println(msg);
UNSAFE.ensureClassInitialized(clazz); try {
MethodHandles.lookup().ensureInitialized(clazz);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
} else { } else {
throw GraalError.shouldNotReachHere(msg); throw GraalError.shouldNotReachHere(msg);
} }

View File

@ -59,7 +59,6 @@ import java.util.Objects;
import java.util.PropertyPermission; import java.util.PropertyPermission;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import jdk.internal.misc.Unsafe;
import jdk.internal.module.Modules; import jdk.internal.module.Modules;
import jdk.jfr.Event; import jdk.jfr.Event;
import jdk.jfr.FlightRecorder; import jdk.jfr.FlightRecorder;
@ -73,7 +72,6 @@ import jdk.jfr.internal.consumer.FileAccess;
* {@link AccessController#doPrivileged(PrivilegedAction)} * {@link AccessController#doPrivileged(PrivilegedAction)}
*/ */
public final class SecuritySupport { public final class SecuritySupport {
private final static Unsafe unsafe = Unsafe.getUnsafe();
private final static MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); private final static MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
private final static Module JFR_MODULE = Event.class.getModule(); private final static Module JFR_MODULE = Event.class.getModule();
public final static SafePath JFC_DIRECTORY = getPathInProperty("java.home", "lib/jfr"); public final static SafePath JFC_DIRECTORY = getPathInProperty("java.home", "lib/jfr");
@ -433,7 +431,11 @@ public final class SecuritySupport {
} }
static void ensureClassIsInitialized(Class<?> clazz) { static void ensureClassIsInitialized(Class<?> clazz) {
unsafe.ensureClassInitialized(clazz); try {
MethodHandles.privateLookupIn(clazz, LOOKUP).ensureInitialized(clazz);
} catch (IllegalAccessException e) {
throw new InternalError(e);
}
} }
static Class<?> defineClass(Class<?> lookupClass, byte[] bytes) { static Class<?> defineClass(Class<?> lookupClass, byte[] bytes) {

View File

@ -699,8 +699,19 @@ public final class Unsafe {
* Detects if the given class may need to be initialized. This is often * Detects if the given class may need to be initialized. This is often
* needed in conjunction with obtaining the static field base of a * needed in conjunction with obtaining the static field base of a
* class. * class.
*
* @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 * @return false only if a call to {@code ensureClassInitialized} would have no effect
*
*/ */
@Deprecated(since = "15", forRemoval = true)
@ForceInline @ForceInline
public boolean shouldBeInitialized(Class<?> c) { public boolean shouldBeInitialized(Class<?> c) {
return theInternalUnsafe.shouldBeInitialized(c); return theInternalUnsafe.shouldBeInitialized(c);
@ -710,7 +721,11 @@ public final class Unsafe {
* Ensures the given class has been initialized. This is often * Ensures the given class has been initialized. This is often
* needed in conjunction with obtaining the static field base of a * needed in conjunction with obtaining the static field base of a
* class. * class.
*
* @deprecated Use the {@link java.lang.invoke.MethodHandles.Lookup#ensureInitialized(Class)}
* method instead. This method is subject to removal in a future version of JDK.
*/ */
@Deprecated(since = "15", forRemoval = true)
@ForceInline @ForceInline
public void ensureClassInitialized(Class<?> c) { public void ensureClassInitialized(Class<?> c) {
theInternalUnsafe.ensureClassInitialized(c); theInternalUnsafe.ensureClassInitialized(c);

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
/**
* @test
* @bug 8235521
* @summary Tests for Lookup::ensureClassInitialized
* @build java.base/* m1/* m2/* Main
* @run testng/othervm --add-modules m1 Main
*/
public class Main {
// Test access to public java.lang class
@Test
public void testPublic() throws Exception {
assertFalse(Helper.isInitialized(PublicInit.class));
MethodHandles.lookup().ensureInitialized(PublicInit.class);
assertTrue(Helper.isInitialized(PublicInit.class));
// no-op if already initialized
MethodHandles.lookup().ensureInitialized(PublicInit.class);
}
// access denied to package-private java.lang class
@Test(expectedExceptions = { IllegalAccessException.class })
public void testPackagePrivate() throws Exception {
Class<?> c = Class.forName("java.lang.DefaultInit", false, null);
assertFalse(Helper.isInitialized(c));
// access denied
MethodHandles.lookup().ensureInitialized(c);
}
// access denied to public class in a non-exported package
@Test(expectedExceptions = { IllegalAccessException.class })
public void testNonExportedPackage() throws Exception {
Class<?> c = Class.forName("jdk.internal.misc.VM", false, null);
// access denied
MethodHandles.lookup().ensureInitialized(c);
}
// invoke p1.Test::test to test module boundary access
@Test
public void testModuleAccess() throws Exception {
Class<?> c = Class.forName("p1.Test");
Method m = c.getMethod("test");
m.invoke(null);
}
@Test(expectedExceptions = { IllegalArgumentException.class })
public void testArrayType() throws Exception {
Class<?> arrayType = PublicInit.class.arrayType();
MethodHandles.lookup().ensureInitialized(arrayType);
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang;
class DefaultInit {
private static boolean initialized;
static {
initialized = true;
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang;
import jdk.internal.misc.Unsafe;
public class Helper {
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
public static boolean isInitialized(Class<?> c) {
return !UNSAFE.shouldBeInitialized(c);
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang;
public class PublicInit {
private static boolean initialized;
static {
initialized = true;
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
module m1 {
requires m2;
exports p1;
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package p1;
import java.lang.invoke.MethodHandles;
public class A {
static final Object lock;
static {
try {
MethodHandles.lookup().ensureInitialized(A.class);
lock = new Object();
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package p1;
class B {
private static final B INSTANCE = new B();
}

View File

@ -0,0 +1,152 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package p1;
import p1.internal.*;
import static java.lang.invoke.MethodHandles.Lookup.*;
import java.lang.invoke.MethodHandles;
/*
* Test::test is invoked by Main class
*/
public class Test {
public static void test() throws Exception {
clinitInvokeEnsureClassInitialized();
testModuleAccess();
testPackageAccess();
testFullPrivilegeAccess();
}
/*
* A::<clinit> calls Lookup::ensureClassInitialized(A.class)
*/
public static void clinitInvokeEnsureClassInitialized() throws Exception {
assertFalse(Helper.isInitialized(A.class));
// same package and public type
MethodHandles.lookup().ensureInitialized(A.class);
assertTrue(Helper.isInitialized(A.class));
}
/*
* Test Lookup with MODULE access to initialize class in this module
* and another module it reads.
*/
public static void testModuleAccess() throws Exception {
MethodHandles.Lookup lookup = MethodHandles.lookup().dropLookupMode(PACKAGE);
assertTrue((lookup.lookupModes() & PACKAGE) == 0);
assertFalse(Helper.isInitialized(p2.T.class));
// exported by another module
lookup.ensureInitialized(p2.T.class);
assertTrue(Helper.isInitialized(p2.T.class));
// non-exported type in another module
Class<?> x = Class.forName(p2.T.class.getModule(), "p2.internal.X");
assertFalse(Helper.isInitialized(x));
try {
lookup.ensureInitialized(x);
throw new AssertionError(lookup + " should not have access to " + x);
} catch (IllegalAccessException e) {}
// no access to package-private class in the same module
try {
lookup.ensureInitialized(E.class);
throw new AssertionError(lookup + " should not have access to " + E.class);
} catch (IllegalAccessException e) {}
}
/*
* Test Lookup with PACKAGE access
*/
public static void testPackageAccess() throws Exception {
MethodHandles.Lookup lookup = MethodHandles.lookup().dropLookupMode(PRIVATE);
assertTrue((lookup.lookupModes() & PRIVATE) == 0);
// verify these classes are not initialized
assertFalse(Helper.isInitialized(B.class));
assertFalse(Helper.isInitialized(C.class));
assertFalse(Helper.isInitialized(E.class));
// same package but package-private
lookup.ensureInitialized(B.class);
assertTrue(Helper.isInitialized(B.class));
// different package and public type
lookup.ensureInitialized(C.class);
assertTrue(Helper.isInitialized(C.class));
// different package and non-public types
Class<?> d = Class.forName(Test.class.getModule(), "p1.internal.D");
assertFalse(Helper.isInitialized(d));
try {
lookup.ensureInitialized(d);
throw new AssertionError(lookup + " should not have access to " + d);
} catch (IllegalAccessException e) {}
}
/*
* Test Lookup with full privilege access
*/
public static void testFullPrivilegeAccess() throws Exception {
MethodHandles.Lookup lookup = MethodHandles.lookup();
// these classes have been initialized
assertTrue(Helper.isInitialized(A.class)); // same package and public type
assertTrue(Helper.isInitialized(B.class)); // same package but package-private
assertTrue(Helper.isInitialized(C.class)); // different package and public type
// verify access to these classes
lookup.ensureInitialized(A.class);
lookup.ensureInitialized(B.class);
lookup.ensureInitialized(C.class);
// different package and non-public types
Class<?> d = Class.forName(Test.class.getModule(), "p1.internal.D");
try {
assertFalse(Helper.isInitialized(d));
lookup.ensureInitialized(d);
throw new AssertionError(lookup + " should not have access to " + d);
} catch (IllegalAccessException e) {}
// nestmate and same package
assertFalse(Helper.isInitialized(E.class));
assertTrue(Test.class.isNestmateOf(E.class));
lookup.ensureInitialized(E.class);
}
public static void assertTrue(boolean v) {
if (!v) {
throw new AssertionError("unexpected result");
}
}
public static void assertFalse(boolean v) {
if (v) {
throw new AssertionError("unexpected result");
}
}
// nestmate
static class E {
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package p1.internal;
public class C {
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package p1.internal;
class D {
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
module m2 {
exports p2 to m1;
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package p2;
public class T {
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package p2.internal;
public class X {
}