8181443: Replace usages of jdk.internal.misc.Unsafe with MethodHandles.Lookup.defineClass

Reviewed-by: alanb, egahlin
This commit is contained in:
Mandy Chung 2018-10-04 08:45:21 -07:00
parent 4af2374271
commit 73a6313038
9 changed files with 56 additions and 41 deletions
src
java.base/share/classes
java/lang
jdk/internal/reflect
jdk.jfr/share/classes/jdk/jfr/internal
test/hotspot/jtreg
compiler
runtime/Dictionary

@ -37,7 +37,6 @@ import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -578,23 +577,17 @@ abstract class ClassSpecializer<T,K,S extends ClassSpecializer<T,K,S>.SpeciesDat
InvokerBytecodeGenerator.maybeDump(classBCName(className), classFile);
Class<?> speciesCode;
ClassLoader cl = topClass().getClassLoader();
ProtectionDomain pd = null;
if (cl != null) {
pd = AccessController.doPrivileged(
new PrivilegedAction<>() {
@Override
public ProtectionDomain run() {
return topClass().getProtectionDomain();
}
});
}
try {
speciesCode = UNSAFE.defineClass(className, classFile, 0, classFile.length, cl, pd);
} catch (Exception ex) {
throw newInternalError(ex);
}
MethodHandles.Lookup lookup = IMPL_LOOKUP.in(topClass());
speciesCode = AccessController.doPrivileged(new PrivilegedAction<>() {
@Override
public Class<?> run() {
try {
return lookup.defineClass(classFile);
} catch (Exception ex) {
throw newInternalError(ex);
}
}
});
return speciesCode.asSubclass(topClass());
}

@ -39,12 +39,11 @@ import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import jdk.internal.loader.BootLoader;
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.module.Modules;
import jdk.internal.misc.Unsafe;
import jdk.internal.misc.VM;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
@ -468,7 +467,7 @@ public class Proxy implements java.io.Serializable {
* in which the proxy class will be defined.
*/
private static final class ProxyBuilder {
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";
@ -535,9 +534,8 @@ public class Proxy implements java.io.Serializable {
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces.toArray(EMPTY_CLASS_ARRAY), accessFlags);
try {
Class<?> pc = UNSAFE.defineClass(proxyName, proxyClassFile,
0, proxyClassFile.length,
loader, null);
Class<?> pc = JLA.defineClass(loader, proxyName, proxyClassFile,
null, "__dynamic_proxy__");
reverseProxyCache.sub(pc).putIfAbsent(loader, Boolean.TRUE);
return pc;
} catch (ClassFormatError e) {

@ -27,14 +27,16 @@ package jdk.internal.reflect;
import java.security.AccessController;
import java.security.PrivilegedAction;
import jdk.internal.misc.Unsafe;
/** Utility class which assists in calling Unsafe.defineClass() by
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.SharedSecrets;
/** Utility class which assists in calling defineClass() by
creating a new class loader which delegates to the one needed in
order for proper resolution of the given bytecodes to occur. */
class ClassDefiner {
static final Unsafe unsafe = Unsafe.getUnsafe();
static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
/** <P> We define generated code into a new class loader which
delegates to the defining loader of the target class. It is
@ -60,7 +62,7 @@ class ClassDefiner {
return new DelegatingClassLoader(parentClassLoader);
}
});
return unsafe.defineClass(name, bytes, off, len, newLoader, null);
return JLA.defineClass(newLoader, name, bytes, null, "__ClassDefiner__");
}
}

@ -70,7 +70,7 @@ public final class EventClassBuilder {
endClass();
byte[] bytes = classWriter.toByteArray();
ASMToolkit.logASM(fullClassName, bytes);
return SecuritySupport.defineClass(type.getInternalName(), bytes, Event.class.getClassLoader()).asSubclass(Event.class);
return SecuritySupport.defineClass(Event.class, bytes).asSubclass(Event.class);
}
private void endClass() {

@ -134,7 +134,7 @@ final class EventHandlerCreator {
buildWriteMethod();
byte[] bytes = classWriter.toByteArray();
ASMToolkit.logASM(className, bytes);
return SecuritySupport.defineClass(className, bytes, Event.class.getClassLoader()).asSubclass(EventHandler.class);
return SecuritySupport.defineClass(EventHandler.class, bytes).asSubclass(EventHandler.class);
}
public static EventHandler instantiateEventHandler(Class<? extends EventHandler> handlerClass, boolean registered, EventType eventType, EventControl eventControl) throws Error {

@ -31,6 +31,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.io.Reader;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@ -71,6 +72,7 @@ import jdk.jfr.Recording;
*/
public final class SecuritySupport {
private final static Unsafe unsafe = Unsafe.getUnsafe();
private final static MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
private final static Module JFR_MODULE = Event.class.getModule();
public final static SafePath JFC_DIRECTORY = getPathInProperty("java.home", "lib/jfr");
@ -381,8 +383,17 @@ public final class SecuritySupport {
unsafe.ensureClassInitialized(clazz);
}
static Class<?> defineClass(String name, byte[] bytes, ClassLoader classLoader) {
return unsafe.defineClass(name, bytes, 0, bytes.length, classLoader, null);
static Class<?> defineClass(Class<?> lookupClass, byte[] bytes) {
return AccessController.doPrivileged(new PrivilegedAction<>() {
@Override
public Class<?> run() {
try {
return MethodHandles.privateLookupIn(lookupClass, LOOKUP).defineClass(bytes);
} catch (IllegalAccessException e) {
throw new InternalError(e);
}
}
});
}
static Thread createThreadWitNoPermissions(String threadName, Runnable runnable) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2018, 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
@ -48,7 +48,6 @@
package compiler.jsr292.NonInlinedCall;
import jdk.internal.misc.Unsafe;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.vm.annotation.DontInline;
@ -68,13 +67,15 @@ import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN;
public class RedefineTest {
static final MethodHandles.Lookup LOOKUP = MethodHandleHelper.IMPL_LOOKUP;
static final Unsafe UNSAFE = Unsafe.getUnsafe();
static final String NAME = "compiler/jsr292/NonInlinedCall/RedefineTest$T";
static Class<?> getClass(int r) {
byte[] classFile = getClassFile(r);
return UNSAFE.defineClass(NAME, classFile, 0, classFile.length, null, null);
try {
return MethodHandles.lookup().defineClass(classFile);
} catch (IllegalAccessException e) {
throw new Error(e);
}
}
/**

@ -32,6 +32,9 @@
* java.base/jdk.internal.vm.annotation
* java.base/jdk.internal.misc
*
* @library ../jsr292/patches
* @build java.base/java.lang.invoke.MethodHandleHelper
*
* @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions
* -Xbatch -XX:-TieredCompilation
* -XX:+FoldStableValues
@ -64,6 +67,9 @@ import jdk.internal.vm.annotation.Stable;
import jdk.test.lib.Asserts;
import jdk.test.lib.Platform;
import java.lang.invoke.MethodHandleHelper;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@ -393,8 +399,9 @@ public class UnsafeGetConstantField {
}
Test generate() {
Class<?> c = U.defineClass(className, classFile, 0, classFile.length, THIS_CLASS.getClassLoader(), null);
try {
Lookup lookup = MethodHandleHelper.IMPL_LOOKUP.in(MethodHandles.class);
Class<?> c = lookup.defineClass(classFile);
return (Test) c.newInstance();
} catch(Exception e) {
throw new Error(e);

@ -57,11 +57,10 @@ public class CleanProtectionDomain {
static class Test {
public static void test() throws Exception {
Unsafe unsafe = Unsafe.getUnsafe();
TestClassLoader classloader = new TestClassLoader();
ProtectionDomain pd = new ProtectionDomain(null, null);
byte klassbuf[] = InMemoryJavaCompiler.compile("TestClass", "class TestClass { }");
Class klass = unsafe.defineClass(null, klassbuf, 0, klassbuf.length, classloader, pd);
Class<?> klass = classloader.defineClass("TestClass", klassbuf, pd);
}
public static void main(String[] args) throws Exception {
@ -91,6 +90,10 @@ public class CleanProtectionDomain {
public TestClassLoader() {
super();
}
public Class<?> defineClass(String name, byte[] bytes, ProtectionDomain pd) {
return defineClass(name, bytes, 0, bytes.length, pd);
}
}
}
}