8226645: [TESTBUG] some AppCDS tests rely on illegal reflective access
authorccheung
Thu, 15 Aug 2019 16:23:41 -0700
changeset 57765 a89ec7fc99aa
parent 57764 2c66dbb94227
child 57766 81ce766c9111
8226645: [TESTBUG] some AppCDS tests rely on illegal reflective access Summary: Updated tests to use Lookup.defineClass instead of ClassLoader.defineClass. Reviewed-by: iklam, dholmes, alanb
test/hotspot/jtreg/runtime/cds/appcds/RewriteBytecodesTest.java
test/hotspot/jtreg/runtime/cds/appcds/customLoader/LoaderSegregationTest.java
test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/LoaderSegregation.java
test/hotspot/jtreg/runtime/cds/appcds/test-classes/RewriteBytecodes.java
test/hotspot/jtreg/runtime/cds/appcds/test-classes/Util.java
--- a/test/hotspot/jtreg/runtime/cds/appcds/RewriteBytecodesTest.java	Thu Aug 15 19:29:58 2019 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/RewriteBytecodesTest.java	Thu Aug 15 16:23:41 2019 -0700
@@ -24,7 +24,7 @@
 
 /*
  * @test
- * @summary Use ClassLoader.defineClass() to load a class with rewritten bytecode. Make sure
+ * @summary Use Lookup.defineClass() to load a class with rewritten bytecode. Make sure
  *          the archived class with the same name is not loaded.
  * @requires vm.cds
  * @library /test/lib
@@ -52,7 +52,6 @@
 
     OutputAnalyzer output = TestCommon.exec(appJar,
                     // command-line arguments ...
-                    "--add-opens=java.base/java.lang=ALL-UNNAMED",
                     use_whitebox_jar,
                     "-XX:+UnlockDiagnosticVMOptions",
                     "-XX:+WhiteBoxAPI",
--- a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/LoaderSegregationTest.java	Thu Aug 15 19:29:58 2019 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/LoaderSegregationTest.java	Thu Aug 15 16:23:41 2019 -0700
@@ -63,7 +63,7 @@
         String wbJar = JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox");
         String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
 
-        String appJar = JarBuilder.build("LoaderSegregation_app", "LoaderSegregation",
+        String appJar = JarBuilder.build("LoaderSegregation_app", "LoaderSegregation", "LoaderSegregation$1",
                                          "CustomLoadee", "CustomLoadee2", "CustomLoadee3Child", "CustomInterface2_ia",
                                          "OnlyBuiltin", "Util");
 
@@ -110,8 +110,6 @@
 
         output = TestCommon.exec(TestCommon.concatPaths(appJar, app2Jar),
                                  // command-line arguments ...
-                                 "--add-opens=java.base/java.lang=ALL-UNNAMED",
-                                 "--add-opens=java.base/java.security=ALL-UNNAMED",
                                  use_whitebox_jar,
                                  "-XX:+UnlockDiagnosticVMOptions",
                                  "-XX:+WhiteBoxAPI",
--- a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/LoaderSegregation.java	Thu Aug 15 19:29:58 2019 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/LoaderSegregation.java	Thu Aug 15 16:23:41 2019 -0700
@@ -81,8 +81,25 @@
         }
 
         { // UNREGISTERED LOADER
-            URLClassLoader urlClassLoader = new URLClassLoader(urls);
-            Class c2 = Util.defineClassFromJAR(urlClassLoader, jarFile, ONLY_BUILTIN);
+            URLClassLoader urlClassLoader = new URLClassLoader(urls) {
+                protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+                    synchronized (getClassLoadingLock(name)) {
+                        Class<?> c = findLoadedClass(name);
+                        if (c == null) {
+                            try {
+                                c = findClass(name);
+                            } catch (ClassNotFoundException e) {
+                                c = getParent().loadClass(name);
+                            }
+                        }
+                        if (resolve) {
+                            resolveClass(c);
+                        }
+                        return c;
+                    }
+                }
+            };
+            Class<?> c2 = urlClassLoader.loadClass(ONLY_BUILTIN);
 
             if (c2.getClassLoader() != urlClassLoader) {
                 throw new RuntimeException("Error in test");
--- a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/RewriteBytecodes.java	Thu Aug 15 19:29:58 2019 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/RewriteBytecodes.java	Thu Aug 15 16:23:41 2019 -0700
@@ -23,6 +23,7 @@
  */
 
 import java.io.File;
+import java.lang.invoke.MethodHandles;
 import sun.hotspot.WhiteBox;
 
 public class RewriteBytecodes {
@@ -30,7 +31,7 @@
     String from = "___xxx___";
     String to   = "___yyy___";
     File clsFile = new File(args[0]);
-    Class superClass = Util.defineModifiedClass(RewriteBytecodes.class.getClassLoader(), clsFile, from, to);
+    Class superClass = Util.defineModifiedClass(MethodHandles.lookup(), clsFile, from, to);
 
     Child child = new Child();
 
--- a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/Util.java	Thu Aug 15 19:29:58 2019 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/Util.java	Thu Aug 15 16:23:41 2019 -0700
@@ -23,19 +23,21 @@
  */
 
 import java.io.*;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.reflect.*;
 import java.util.jar.*;
 
 public class Util {
     /**
-     * Invoke the loader.defineClass() class method to define the class stored in clsFile,
+     * Define the class as stored in clsFile with the provided lookup instance,
      * with the following modification:
      * <ul>
      *  <li> All ASCII strings in the class file bytes that matches fromString will be replaced with toString.
      *       NOTE: the two strings must be the exact same length.
      * </ul>
      */
-    public static Class defineModifiedClass(ClassLoader loader, File clsFile, String fromString, String toString)
+    public static Class<?> defineModifiedClass(Lookup lookup, File clsFile, String fromString, String toString)
         throws FileNotFoundException, IOException, NoSuchMethodException, IllegalAccessException,
                InvocationTargetException
     {
@@ -46,14 +48,11 @@
 
         System.out.println("Loading from: " + clsFile + " (" + buff.length + " bytes)");
 
-        Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass",
-                                                                 buff.getClass(), int.class, int.class);
-        defineClass.setAccessible(true);
 
-        // We directly call into ClassLoader.defineClass() to define the "Super" class. Also,
+        // We directly call into Lookup.defineClass() to define the "Super" class. Also,
         // rewrite its classfile so that it returns ___yyy___ instead of ___xxx___. Changing the
         // classfile will guarantee that this class will NOT be loaded from the CDS archive.
-        Class cls = (Class)defineClass.invoke(loader, buff, new Integer(0), new Integer(buff.length));
+        Class<?> cls = lookup.defineClass(buff);
         System.out.println("Loaded : " + cls);
 
         return cls;
@@ -105,44 +104,6 @@
         return b;
     }
 
-    public static Class defineClassFromJAR(ClassLoader loader, File jarFile, String className)
-        throws FileNotFoundException, IOException, NoSuchMethodException, IllegalAccessException,
-               InvocationTargetException {
-        return defineClassFromJAR(loader, jarFile, className, null, null);
-    }
-
-    /**
-     * Invoke the loader.defineClass() class method to define the named class stored in a JAR file.
-     *
-     * If a class exists both in the classpath, as well as in the list of URLs of a URLClassLoader,
-     * by default, the URLClassLoader will not define the class, and instead will delegate to the
-     * app loader. This method is an easy way to force the class to be defined by the URLClassLoader.
-     *
-     * Optionally, you can modify the contents of the classfile buffer. See comments in
-     * defineModifiedClass.
-     */
-    public static Class defineClassFromJAR(ClassLoader loader, File jarFile, String className,
-                                           String fromString, String toString)
-        throws FileNotFoundException, IOException, NoSuchMethodException, IllegalAccessException,
-               InvocationTargetException
-    {
-        byte[] buff = getClassFileFromJar(jarFile, className);
-
-        if (fromString != null) {
-            replace(buff, fromString, toString);
-        }
-
-        //System.out.println("Loading from: " + ent + " (" + buff.length + " bytes)");
-
-        Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass",
-                                                                 buff.getClass(), int.class, int.class);
-        defineClass.setAccessible(true);
-        Class cls = (Class)defineClass.invoke(loader, buff, new Integer(0), new Integer(buff.length));
-
-        //System.out.println("Loaded : " + cls);
-        return cls;
-    }
-
     public static byte[] getClassFileFromJar(File jarFile, String className) throws FileNotFoundException, IOException {
         JarFile jf = new JarFile(jarFile);
         JarEntry ent = jf.getJarEntry(className.replace('.', '/') + ".class");