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.SharedSecrets;
import jdk.internal.misc.Unsafe;
import jdk.internal.misc.VM;
import jdk.internal.module.IllegalAccessLogger;
import jdk.internal.org.objectweb.asm.ClassReader;
@ -2243,7 +2244,8 @@ public class MethodHandles {
Class<?> lookupClass = lookup.lookupClass();
ClassLoader loader = lookupClass.getClassLoader();
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();
return c;
}
@ -2263,7 +2265,7 @@ public class MethodHandles {
private ProtectionDomain lookupClassProtectionDomain() {
ProtectionDomain pd = cachedProtectionDomain;
if (pd == null) {
cachedProtectionDomain = pd = JLA.protectionDomain(lookupClass);
cachedProtectionDomain = pd = SharedSecrets.getJavaLangAccess().protectionDomain(lookupClass);
}
return pd;
}
@ -2283,8 +2285,6 @@ public class MethodHandles {
*/
static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, null, UNCONDITIONAL);
static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
String name = lookupClass.getName();
if (name.startsWith("java.lang.invoke."))
@ -2586,6 +2586,43 @@ assertEquals("[x, y, z]", pb.command().toString());
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
* 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 java.io.ObjectInputFilter;
import java.lang.invoke.MethodHandles;
import java.lang.module.ModuleDescriptor;
import java.util.ResourceBundle;
import java.util.jar.JarFile;
@ -37,7 +38,6 @@ import java.io.ObjectInputStream;
import java.io.RandomAccessFile;
import java.security.ProtectionDomain;
import java.security.Signature;
import jdk.internal.misc.Unsafe;
/** A repository of "shared secrets", which are a mechanism for
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. */
public class SharedSecrets {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
private static JavaAWTAccess javaAWTAccess;
private static JavaAWTFontAccess javaAWTFontAccess;
private static JavaBeansAccess javaBeansAccess;
@ -81,7 +81,7 @@ public class SharedSecrets {
if (javaUtilJarAccess == null) {
// Ensure JarFile is initialized; we know that this class
// provides the shared secret
unsafe.ensureClassInitialized(JarFile.class);
ensureClassInitialized(JarFile.class);
}
return javaUtilJarAccess;
}
@ -105,8 +105,7 @@ public class SharedSecrets {
public static JavaLangInvokeAccess getJavaLangInvokeAccess() {
if (javaLangInvokeAccess == null) {
try {
Class<?> c = Class.forName("java.lang.invoke.MethodHandleImpl");
unsafe.ensureClassInitialized(c);
Class.forName("java.lang.invoke.MethodHandleImpl", true, null);
} catch (ClassNotFoundException e) {};
}
return javaLangInvokeAccess;
@ -118,7 +117,7 @@ public class SharedSecrets {
public static JavaLangModuleAccess getJavaLangModuleAccess() {
if (javaLangModuleAccess == null) {
unsafe.ensureClassInitialized(ModuleDescriptor.class);
ensureClassInitialized(ModuleDescriptor.class);
}
return javaLangModuleAccess;
}
@ -145,7 +144,7 @@ public class SharedSecrets {
public static JavaNetUriAccess getJavaNetUriAccess() {
if (javaNetUriAccess == null)
unsafe.ensureClassInitialized(java.net.URI.class);
ensureClassInitialized(java.net.URI.class);
return javaNetUriAccess;
}
@ -155,7 +154,7 @@ public class SharedSecrets {
public static JavaNetURLAccess getJavaNetURLAccess() {
if (javaNetURLAccess == null)
unsafe.ensureClassInitialized(java.net.URL.class);
ensureClassInitialized(java.net.URL.class);
return javaNetURLAccess;
}
@ -165,7 +164,7 @@ public class SharedSecrets {
public static JavaNetInetAddressAccess getJavaNetInetAddressAccess() {
if (javaNetInetAddressAccess == null)
unsafe.ensureClassInitialized(java.net.InetAddress.class);
ensureClassInitialized(java.net.InetAddress.class);
return javaNetInetAddressAccess;
}
@ -175,7 +174,7 @@ public class SharedSecrets {
public static JavaNetHttpCookieAccess getJavaNetHttpCookieAccess() {
if (javaNetHttpCookieAccess == null)
unsafe.ensureClassInitialized(java.net.HttpCookie.class);
ensureClassInitialized(java.net.HttpCookie.class);
return javaNetHttpCookieAccess;
}
@ -187,7 +186,7 @@ public class SharedSecrets {
if (javaNioAccess == null) {
// Ensure java.nio.Buffer is initialized, which provides the
// shared secret.
unsafe.ensureClassInitialized(java.nio.Buffer.class);
ensureClassInitialized(java.nio.Buffer.class);
}
return javaNioAccess;
}
@ -198,7 +197,7 @@ public class SharedSecrets {
public static JavaIOAccess getJavaIOAccess() {
if (javaIOAccess == null) {
unsafe.ensureClassInitialized(Console.class);
ensureClassInitialized(Console.class);
}
return javaIOAccess;
}
@ -209,7 +208,7 @@ public class SharedSecrets {
public static JavaIOFilePermissionAccess getJavaIOFilePermissionAccess() {
if (javaIOFilePermissionAccess == null)
unsafe.ensureClassInitialized(FilePermission.class);
ensureClassInitialized(FilePermission.class);
return javaIOFilePermissionAccess;
}
@ -220,7 +219,7 @@ public class SharedSecrets {
public static JavaIOFileDescriptorAccess getJavaIOFileDescriptorAccess() {
if (javaIOFileDescriptorAccess == null)
unsafe.ensureClassInitialized(FileDescriptor.class);
ensureClassInitialized(FileDescriptor.class);
return javaIOFileDescriptorAccess;
}
@ -231,14 +230,14 @@ public class SharedSecrets {
public static JavaSecurityAccess getJavaSecurityAccess() {
if (javaSecurityAccess == null) {
unsafe.ensureClassInitialized(ProtectionDomain.class);
ensureClassInitialized(ProtectionDomain.class);
}
return javaSecurityAccess;
}
public static JavaUtilZipFileAccess getJavaUtilZipFileAccess() {
if (javaUtilZipFileAccess == null)
unsafe.ensureClassInitialized(java.util.zip.ZipFile.class);
ensureClassInitialized(java.util.zip.ZipFile.class);
return javaUtilZipFileAccess;
}
@ -276,7 +275,7 @@ public class SharedSecrets {
public static JavaUtilResourceBundleAccess getJavaUtilResourceBundleAccess() {
if (javaUtilResourceBundleAccess == null)
unsafe.ensureClassInitialized(ResourceBundle.class);
ensureClassInitialized(ResourceBundle.class);
return javaUtilResourceBundleAccess;
}
@ -286,7 +285,7 @@ public class SharedSecrets {
public static JavaObjectInputStreamReadString getJavaObjectInputStreamReadString() {
if (javaObjectInputStreamReadString == null) {
unsafe.ensureClassInitialized(ObjectInputStream.class);
ensureClassInitialized(ObjectInputStream.class);
}
return javaObjectInputStreamReadString;
}
@ -297,7 +296,7 @@ public class SharedSecrets {
public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() {
if (javaObjectInputStreamAccess == null) {
unsafe.ensureClassInitialized(ObjectInputStream.class);
ensureClassInitialized(ObjectInputStream.class);
}
return javaObjectInputStreamAccess;
}
@ -308,7 +307,7 @@ public class SharedSecrets {
public static JavaObjectInputFilterAccess getJavaObjectInputFilterAccess() {
if (javaObjectInputFilterAccess == null) {
unsafe.ensureClassInitialized(ObjectInputFilter.Config.class);
ensureClassInitialized(ObjectInputFilter.Config.class);
}
return javaObjectInputFilterAccess;
}
@ -323,7 +322,7 @@ public class SharedSecrets {
public static JavaIORandomAccessFileAccess getJavaIORandomAccessFileAccess() {
if (javaIORandomAccessFileAccess == null) {
unsafe.ensureClassInitialized(RandomAccessFile.class);
ensureClassInitialized(RandomAccessFile.class);
}
return javaIORandomAccessFileAccess;
}
@ -334,7 +333,7 @@ public class SharedSecrets {
public static JavaSecuritySignatureAccess getJavaSecuritySignatureAccess() {
if (javaSecuritySignatureAccess == null) {
unsafe.ensureClassInitialized(Signature.class);
ensureClassInitialized(Signature.class);
}
return javaSecuritySignatureAccess;
}
@ -345,8 +344,14 @@ public class SharedSecrets {
public static JavaxCryptoSealedObjectAccess getJavaxCryptoSealedObjectAccess() {
if (javaxCryptoSealedObjectAccess == null) {
unsafe.ensureClassInitialized(SealedObject.class);
ensureClassInitialized(SealedObject.class);
}
return javaxCryptoSealedObjectAccess;
}
private static void ensureClassInitialized(Class<?> c) {
try {
MethodHandles.lookup().ensureInitialized(c);
} catch (IllegalAccessException e) {}
}
}