8181443: Replace usages of jdk.internal.misc.Unsafe with MethodHandles.Lookup.defineClass
authormchung
Thu, 04 Oct 2018 08:45:21 -0700
changeset 52015 821bfc24d750
parent 52014 1aa9beac610e
child 52016 9ea22a0f9540
8181443: Replace usages of jdk.internal.misc.Unsafe with MethodHandles.Lookup.defineClass Reviewed-by: alanb, egahlin
src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java
src/java.base/share/classes/java/lang/reflect/Proxy.java
src/java.base/share/classes/jdk/internal/reflect/ClassDefiner.java
src/jdk.jfr/share/classes/jdk/jfr/internal/EventClassBuilder.java
src/jdk.jfr/share/classes/jdk/jfr/internal/EventHandlerCreator.java
src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java
test/hotspot/jtreg/compiler/jsr292/NonInlinedCall/RedefineTest.java
test/hotspot/jtreg/compiler/unsafe/UnsafeGetConstantField.java
test/hotspot/jtreg/runtime/Dictionary/CleanProtectionDomain.java
--- 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);
+      }
     }
   }
 }