8181443: Replace usages of jdk.internal.misc.Unsafe with MethodHandles.Lookup.defineClass
Reviewed-by: alanb, egahlin
--- a/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java Thu Oct 04 16:39:07 2018 +0200
+++ b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java Thu Oct 04 08:45:21 2018 -0700
@@ -37,7 +37,6 @@
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 @@
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());
}
--- a/src/java.base/share/classes/java/lang/reflect/Proxy.java Thu Oct 04 16:39:07 2018 +0200
+++ b/src/java.base/share/classes/java/lang/reflect/Proxy.java Thu Oct 04 08:45:21 2018 -0700
@@ -39,12 +39,11 @@
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 @@
* 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 @@
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) {
--- a/src/java.base/share/classes/jdk/internal/reflect/ClassDefiner.java Thu Oct 04 16:39:07 2018 +0200
+++ b/src/java.base/share/classes/jdk/internal/reflect/ClassDefiner.java Thu Oct 04 08:45:21 2018 -0700
@@ -27,14 +27,16 @@
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 @@
return new DelegatingClassLoader(parentClassLoader);
}
});
- return unsafe.defineClass(name, bytes, off, len, newLoader, null);
+ return JLA.defineClass(newLoader, name, bytes, null, "__ClassDefiner__");
}
}
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventClassBuilder.java Thu Oct 04 16:39:07 2018 +0200
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventClassBuilder.java Thu Oct 04 08:45:21 2018 -0700
@@ -70,7 +70,7 @@
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() {
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventHandlerCreator.java Thu Oct 04 16:39:07 2018 +0200
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventHandlerCreator.java Thu Oct 04 08:45:21 2018 -0700
@@ -134,7 +134,7 @@
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 {
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java Thu Oct 04 16:39:07 2018 +0200
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java Thu Oct 04 08:45:21 2018 -0700
@@ -31,6 +31,7 @@
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 @@
*/
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 @@
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) {
--- a/test/hotspot/jtreg/compiler/jsr292/NonInlinedCall/RedefineTest.java Thu Oct 04 16:39:07 2018 +0200
+++ b/test/hotspot/jtreg/compiler/jsr292/NonInlinedCall/RedefineTest.java Thu Oct 04 08:45:21 2018 -0700
@@ -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 @@
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);
+ }
}
/**
--- a/test/hotspot/jtreg/compiler/unsafe/UnsafeGetConstantField.java Thu Oct 04 16:39:07 2018 +0200
+++ b/test/hotspot/jtreg/compiler/unsafe/UnsafeGetConstantField.java Thu Oct 04 08:45:21 2018 -0700
@@ -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.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 @@
}
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);
--- a/test/hotspot/jtreg/runtime/Dictionary/CleanProtectionDomain.java Thu Oct 04 16:39:07 2018 +0200
+++ b/test/hotspot/jtreg/runtime/Dictionary/CleanProtectionDomain.java Thu Oct 04 08:45:21 2018 -0700
@@ -57,11 +57,10 @@
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 TestClassLoader() {
super();
}
+
+ public Class<?> defineClass(String name, byte[] bytes, ProtectionDomain pd) {
+ return defineClass(name, bytes, 0, bytes.length, pd);
+ }
}
}
}