changeset 8876:270570f695e0 jdk8u202-b04

Merge
author aefimov
date Thu, 08 Nov 2018 18:33:43 +0000
parents 0cd448a4edaf (current diff) f85cae50e040 (diff)
children 2cf91d9cb013
files .hgtags src/share/vm/classfile/systemDictionary.cpp src/share/vm/classfile/verificationType.cpp src/share/vm/oops/constantPool.cpp src/share/vm/prims/jvm.cpp
diffstat 15 files changed, 405 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Wed Nov 07 05:13:44 2018 -0800
+++ b/.hgtags	Thu Nov 08 18:33:43 2018 +0000
@@ -1189,6 +1189,7 @@
 464ed8cea5d6cdbfacc9be7035297af88f57f708 jdk8u181-b12
 eed8e846c982d7474dd07fc873ba02f83ad1f847 jdk8u181-b13
 21a3fffc43418f4d75c2091bf03478330b8a9a98 jdk8u191-b01
+2bf8498a25ec87c92584a6542f8724644c8c5706 jdk8u201-b00
 5aa3d728164a674d08ad847811be6bdd853e9bf8 jdk8u191-b02
 dd79b482625361458b2b34e7d669ee982eee06a4 jdk8u191-b03
 541c205d7fd15ab840f48aaeeaea3f63209d1687 jdk8u191-b04
@@ -1219,6 +1220,16 @@
 8df818c645d6081a387cf4fe9b9c14c0b5b639b1 jdk8u192-b11
 1f822ff877d1a250165d5d2d52faf6957f8fcd00 jdk8u192-b12
 e0e4c3a86ef0e4daf4fe96bd058045a2b13ebf84 jdk8u192-b26
+f7bd3ef62b03503c2abd2c877103fce4c41752ec jdk8u181-b31
+a2be8e761961b9aea1641593f2638406c8052bff jdk8u181-b32
+9d9f4c81eb3df5991f4409429a8eed5da385e138 jdk8u181-b33
+2ac6a4ff7b3c9c45bda2a449523f7f1babffd857 jdk8u181-b34
+f3eb9719e6961890add8af56c43a3273bedd3510 jdk8u181-b35
+5418d85b93ea93af1b75a700501cab9e53e282c5 jdk8u181-b36
+310a8a03be9363e47cc0856e43661cf71b516101 jdk8u181-b37
+cec91c1510a4f6b54f454f8a18c2ce19e1ef4002 jdk8u201-b01
+242132d678006ccd4139c33c1a188f09a09683c6 jdk8u201-b02
+68ee3b18354df0572de37bc04c3a7a8046d5a654 jdk8u201-b03
 79b4c0a88c00226dcd14496652adf84d53b5cb9c jdk8u202-b01
 9ce27f0a4683a2083d3aed59a40d6a3ccfc8e397 jdk8u202-b02
 c0836eee40e5cfc7b3eebbb7a53bfcd98bc66278 jdk8u202-b03
--- a/src/share/vm/classfile/classFileParser.cpp	Wed Nov 07 05:13:44 2018 -0800
+++ b/src/share/vm/classfile/classFileParser.cpp	Thu Nov 08 18:33:43 2018 +0000
@@ -4210,9 +4210,6 @@
           this_klass(), &all_mirandas, CHECK_(nullHandle));
     }
 
-    // Update the loader_data graph.
-    record_defined_class_dependencies(this_klass, CHECK_NULL);
-
     ClassLoadingService::notify_class_loaded(InstanceKlass::cast(this_klass()),
                                              false /* not shared class */);
 
@@ -4498,30 +4495,6 @@
   }
 }
 
-// Attach super classes and interface classes to class loader data
-void ClassFileParser::record_defined_class_dependencies(instanceKlassHandle defined_klass, TRAPS) {
-  ClassLoaderData * defining_loader_data = defined_klass->class_loader_data();
-  if (defining_loader_data->is_the_null_class_loader_data()) {
-      // Dependencies to null class loader data are implicit.
-      return;
-  } else {
-    // add super class dependency
-    Klass* super = defined_klass->super();
-    if (super != NULL) {
-      defining_loader_data->record_dependency(super, CHECK);
-    }
-
-    // add super interface dependencies
-    Array<Klass*>* local_interfaces = defined_klass->local_interfaces();
-    if (local_interfaces != NULL) {
-      int length = local_interfaces->length();
-      for (int i = 0; i < length; i++) {
-        defining_loader_data->record_dependency(local_interfaces->at(i), CHECK);
-      }
-    }
-  }
-}
-
 // utility methods for appending an array with check for duplicates
 
 void append_interfaces(GrowableArray<Klass*>* result, Array<Klass*>* ifs) {
--- a/src/share/vm/classfile/dictionary.cpp	Wed Nov 07 05:13:44 2018 -0800
+++ b/src/share/vm/classfile/dictionary.cpp	Thu Nov 08 18:33:43 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -159,33 +159,9 @@
       if (!is_strongly_reachable(loader_data, e)) {
         // Entry was not visited in phase1 (negated test from phase1)
         assert(!loader_data->is_the_null_class_loader_data(), "unloading entry with null class loader");
-        ClassLoaderData* k_def_class_loader_data = ik->class_loader_data();
-
-        // Do we need to delete this system dictionary entry?
-        bool purge_entry = false;
 
         // Do we need to delete this system dictionary entry?
         if (loader_data->is_unloading()) {
-          // If the loader is not live this entry should always be
-          // removed (will never be looked up again).
-          purge_entry = true;
-        } else {
-          // The loader in this entry is alive. If the klass is dead,
-          // (determined by checking the defining class loader)
-          // the loader must be an initiating loader (rather than the
-          // defining loader). Remove this entry.
-          if (k_def_class_loader_data->is_unloading()) {
-            // If we get here, the class_loader_data must not be the defining
-            // loader, it must be an initiating one.
-            assert(k_def_class_loader_data != loader_data,
-                   "cannot have live defining loader and unreachable klass");
-            // Loader is live, but class and its defining loader are dead.
-            // Remove the entry. The class is going away.
-            purge_entry = true;
-          }
-        }
-
-        if (purge_entry) {
           *p = probe->next();
           if (probe == _current_class_entry) {
             _current_class_entry = NULL;
--- a/src/share/vm/classfile/systemDictionary.cpp	Wed Nov 07 05:13:44 2018 -0800
+++ b/src/share/vm/classfile/systemDictionary.cpp	Thu Nov 08 18:33:43 2018 +0000
@@ -816,7 +816,16 @@
         check_constraints(d_index, d_hash, k, class_loader, false, THREAD);
 
         // Need to check for a PENDING_EXCEPTION again; check_constraints
-        // can throw and doesn't use the CHECK macro.
+        // can throw but we may have to remove entry from the placeholder table below.
+        if (!HAS_PENDING_EXCEPTION) {
+          // Record dependency for non-parent delegation.
+          // This recording keeps the defining class loader of the klass (k) found
+          // from being unloaded while the initiating class loader is loaded
+          // even if the reference to the defining class loader is dropped
+          // before references to the initiating class loader.
+          loader_data->record_dependency(k(), THREAD);
+        }
+
         if (!HAS_PENDING_EXCEPTION) {
           { // Grabbing the Compile_lock prevents systemDictionary updates
             // during compilations.
--- a/src/share/vm/classfile/verificationType.cpp	Wed Nov 07 05:13:44 2018 -0800
+++ b/src/share/vm/classfile/verificationType.cpp	Thu Nov 08 18:33:43 2018 +0000
@@ -63,7 +63,6 @@
         name(), Handle(THREAD, klass->class_loader()),
         Handle(THREAD, klass->protection_domain()), true, CHECK_false);
     KlassHandle this_class(THREAD, obj);
-    klass->class_loader_data()->record_dependency(obj, CHECK_false);
 
     if (this_class->is_interface() && (!from_field_is_protected ||
         from.name() != vmSymbols::java_lang_Object())) {
@@ -75,7 +74,6 @@
       Klass* from_class = SystemDictionary::resolve_or_fail(
           from.name(), Handle(THREAD, klass->class_loader()),
           Handle(THREAD, klass->protection_domain()), true, CHECK_false);
-      klass->class_loader_data()->record_dependency(from_class, CHECK_false);
       bool result = InstanceKlass::cast(from_class)->is_subclass_of(this_class());
       if (result && DumpSharedSpaces) {
         if (klass()->is_subclass_of(from_class) && klass()->is_subclass_of(this_class())) {
--- a/src/share/vm/classfile/verifier.cpp	Wed Nov 07 05:13:44 2018 -0800
+++ b/src/share/vm/classfile/verifier.cpp	Thu Nov 08 18:33:43 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -1949,11 +1949,9 @@
   oop loader = current_class()->class_loader();
   oop protection_domain = current_class()->protection_domain();
 
-  Klass* kls = SystemDictionary::resolve_or_fail(
+  return SystemDictionary::resolve_or_fail(
     name, Handle(THREAD, loader), Handle(THREAD, protection_domain),
     true, CHECK_NULL);
-  current_class()->class_loader_data()->record_dependency(kls, CHECK_NULL);
-  return kls;
 }
 
 bool ClassVerifier::is_protected_access(instanceKlassHandle this_class,
--- a/src/share/vm/oops/constantPool.cpp	Wed Nov 07 05:13:44 2018 -0800
+++ b/src/share/vm/oops/constantPool.cpp	Thu Nov 08 18:33:43 2018 +0000
@@ -339,8 +339,6 @@
       // Only updated constant pool - if it is resolved.
       do_resolve = this_oop->tag_at(which).is_unresolved_klass();
       if (do_resolve) {
-        ClassLoaderData* this_key = this_oop->pool_holder()->class_loader_data();
-        this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM
         this_oop->klass_at_put(which, k());
       }
     }
--- a/src/share/vm/oops/cpCache.cpp	Wed Nov 07 05:13:44 2018 -0800
+++ b/src/share/vm/oops/cpCache.cpp	Thu Nov 08 18:33:43 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -209,12 +209,22 @@
   if (byte_no == 1) {
     assert(invoke_code != Bytecodes::_invokevirtual &&
            invoke_code != Bytecodes::_invokeinterface, "");
+    bool do_resolve = true;
     // Don't mark invokespecial to method as resolved if sender is an interface.  The receiver
     // has to be checked that it is a subclass of the current class every time this bytecode
     // is executed.
-    if (invoke_code != Bytecodes::_invokespecial || !sender_is_interface ||
-        method->name() == vmSymbols::object_initializer_name()) {
-    set_bytecode_1(invoke_code);
+    if (invoke_code == Bytecodes::_invokespecial && sender_is_interface &&
+        method->name() != vmSymbols::object_initializer_name()) {
+      do_resolve = false;
+    }
+    // Don't mark invokestatic to method as resolved if the holder class has not yet completed
+    // initialization. An invokestatic must only proceed if the class is initialized, but if
+    // we resolve it before then that class initialization check is skipped.
+    if (invoke_code == Bytecodes::_invokestatic && !method->method_holder()->is_initialized()) {
+      do_resolve = false;
+    }
+    if (do_resolve) {
+        set_bytecode_1(invoke_code);
     }
   } else if (byte_no == 2)  {
     if (change_to_virtual) {
--- a/src/share/vm/prims/jvm.cpp	Wed Nov 07 05:13:44 2018 -0800
+++ b/src/share/vm/prims/jvm.cpp	Thu Nov 08 18:33:43 2018 +0000
@@ -991,12 +991,6 @@
   Handle h_prot  (THREAD, protection_domain);
   jclass result = find_class_from_class_loader(env, h_name, init, h_loader,
                                                h_prot, true, thread);
-  if (result != NULL) {
-    oop mirror = JNIHandles::resolve_non_null(result);
-    Klass* to_class = java_lang_Class::as_Klass(mirror);
-    ClassLoaderData* cld = ClassLoaderData::class_loader_data(h_loader());
-    cld->record_dependency(to_class, CHECK_NULL);
-  }
 
   if (TraceClassResolution && result != NULL) {
     // this function is generally only used for class loading during verification.
--- a/src/share/vm/runtime/sharedRuntime.cpp	Wed Nov 07 05:13:44 2018 -0800
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Thu Nov 08 18:33:43 2018 +0000
@@ -1232,6 +1232,14 @@
   }
 #endif
 
+  // Do not patch call site for static call when the class is not
+  // fully initialized.
+  if (invoke_code == Bytecodes::_invokestatic &&
+      !callee_method->method_holder()->is_initialized()) {
+    assert(callee_method->method_holder()->is_linked(), "must be");
+    return callee_method;
+  }
+
   // JSR 292 key invariant:
   // If the resolved method is a MethodHandle invoke target, the call
   // site must be a MethodHandle call site, because the lambda form might tail-call
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/ClassUnload/ConstantPoolDependsTest.java	Thu Nov 08 18:33:43 2018 +0000
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test ConstantPoolDependsTest
+ * @bug 8210094
+ * @summary Create ClassLoader dependency from initiating loader to class loader through constant pool reference
+ * @modules java.base/jdk.internal.misc
+ *          java.compiler
+ * @library /testlibrary /testlibrary/whitebox /runtime/testlibrary
+ * @build sun.hotspot.WhiteBox
+ * @compile p2/c2.java MyDiffClassLoader.java
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ConstantPoolDependsTest
+ */
+
+import sun.hotspot.WhiteBox;
+
+
+public class ConstantPoolDependsTest {
+    public static WhiteBox wb = WhiteBox.getWhiteBox();
+    public static final String MY_TEST = "ConstantPoolDependsTest$c1c";
+
+    public static class c1c {
+        private void test() throws Exception {
+            // ConstantPool.klass_at_impl loads through constant pool and creates dependency
+            p2.c2 c2_obj = new p2.c2();
+            c2_obj.method2();
+        }
+
+        public c1c () throws Exception {
+            test();
+            ClassUnloadCommon.triggerUnloading();  // should not unload anything
+            test();
+            ClassUnloadCommon.triggerUnloading();  // should not unload anything
+        }
+    }
+
+    static void test() throws Throwable {
+
+        // now use the same loader to load class MyTest
+        Class MyTest_class = new MyDiffClassLoader(MY_TEST).loadClass(MY_TEST);
+
+        try {
+            // Call MyTest to load p2.c2 twice and call p2.c2.method2
+            MyTest_class.newInstance();
+        } catch (Exception e) {
+            throw new RuntimeException("Test FAILED if NoSuchMethodException is thrown");
+        }
+        ClassUnloadCommon.triggerUnloading();  // should not unload anything
+        ClassUnloadCommon.failIf(!wb.isClassAlive(MY_TEST), "should not be unloaded");
+        ClassUnloadCommon.failIf(!wb.isClassAlive("p2.c2"), "should not be unloaded");
+        // Unless MyTest_class is referenced here, the compiler can unload it.
+        System.out.println("Should not unload anything before here because " + MyTest_class + " is still alive.");
+    }
+
+    public static void main(String args[]) throws Throwable {
+        test();
+        ClassUnloadCommon.triggerUnloading();  // should unload
+        System.gc();
+        System.out.println("Should unload p2.c2 just now");
+        ClassUnloadCommon.failIf(wb.isClassAlive(MY_TEST), "should be unloaded");
+        ClassUnloadCommon.failIf(wb.isClassAlive("p2.c2"), "should be unloaded");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/ClassUnload/DictionaryDependsTest.java	Thu Nov 08 18:33:43 2018 +0000
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test DictionaryDependsTest
+ * @bug 8210094
+ * @summary Create ClassLoader dependency from initiating loader to class loader through reflection
+ * @modules java.base/jdk.internal.misc
+ *          java.compiler
+ * @library /testlibrary /testlibrary/whitebox /runtime/testlibrary
+ * @build sun.hotspot.WhiteBox
+ * @compile p2/c2.java MyDiffClassLoader.java
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI DictionaryDependsTest
+ */
+import sun.hotspot.WhiteBox;
+import java.lang.reflect.Method;
+
+public class DictionaryDependsTest {
+    public static WhiteBox wb = WhiteBox.getWhiteBox();
+    public static final String MY_TEST = "DictionaryDependsTest$c1r";
+
+    static public class c1r {
+
+        private void test() throws Exception {
+            // forName loads through reflection and doesn't create dependency
+            Class<?> x = Class.forName("p2.c2", true, c1r.class.getClassLoader());
+            Method m = x.getMethod("method2");
+            java.lang.Object t = x.newInstance();
+            m.invoke(t);
+        }
+
+        public c1r () throws Exception {
+            test();
+            ClassUnloadCommon.triggerUnloading();  // should unload p2.c2
+            test();
+            ClassUnloadCommon.triggerUnloading();  // should unload p2.c2
+        }
+    }
+
+    public void test() throws Throwable {
+
+        // now use the same loader to load class MyTest
+        Class MyTest_class = new MyDiffClassLoader(MY_TEST).loadClass(MY_TEST);
+
+        try {
+            // Call MyTest to load p2.c2 twice and call p2.c2.method2
+            MyTest_class.newInstance();
+        } catch (Exception e) {
+            System.out.println("Not expected NSME");
+            throw new RuntimeException("Not expecting NSME");
+        }
+        ClassUnloadCommon.triggerUnloading();  // should not unload anything
+        ClassUnloadCommon.failIf(!wb.isClassAlive(MY_TEST), "should not be unloaded");
+        ClassUnloadCommon.failIf(!wb.isClassAlive("p2.c2"), "should not be unloaded");
+        // Unless MyTest_class is referenced here, the compiler can unload it.
+        System.out.println("Should not unload anything before here because " + MyTest_class + " is still alive.");
+    }
+
+    public static void main(String args[]) throws Throwable {
+        DictionaryDependsTest d = new DictionaryDependsTest();
+        d.test();
+        ClassUnloadCommon.triggerUnloading();  // should not unload anything
+        System.out.println("Should unload MyTest and p2.c2 just now");
+        ClassUnloadCommon.failIf(wb.isClassAlive(MY_TEST), "should be unloaded");
+        ClassUnloadCommon.failIf(wb.isClassAlive("p2.c2"), "should be unloaded");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/ClassUnload/MyDiffClassLoader.java	Thu Nov 08 18:33:43 2018 +0000
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.*;
+import com.oracle.java.testlibrary.InMemoryJavaCompiler;
+
+public class MyDiffClassLoader extends ClassLoader {
+
+    public String loaderName;
+    public static boolean switchClassData = false;
+
+    MyDiffClassLoader(String name) {
+        this.loaderName = name;
+    }
+
+    public Class loadClass(String name) throws ClassNotFoundException {
+        if (!name.contains("c1r") &&
+            !name.contains("c1c") &&
+            !name.contains("c1s") &&
+            !name.equals("p2.c2")) {
+                return super.loadClass(name);
+        }
+
+        // new loader loads p2.c2
+        if  (name.equals("p2.c2") && !loaderName.equals("C2Loader")) {
+            Class<?> c = new MyDiffClassLoader("C2Loader").loadClass(name);
+            switchClassData = true;
+            return c;
+        }
+
+        byte[] data = switchClassData ? getNewClassData(name) : getClassData(name);
+        System.out.println("name is " + name);
+        return defineClass(name, data, 0, data.length);
+    }
+    byte[] getClassData(String name) {
+        try {
+           String TempName = name.replaceAll("\\.", "/");
+           String currentDir = System.getProperty("test.classes");
+           String filename = currentDir + File.separator + TempName + ".class";
+           FileInputStream fis = new FileInputStream(filename);
+           byte[] b = new byte[5000];
+           int cnt = fis.read(b, 0, 5000);
+           byte[] c = new byte[cnt];
+           for (int i=0; i<cnt; i++) c[i] = b[i];
+             return c;
+        } catch (IOException e) {
+           return null;
+        }
+    }
+
+    // Return p2.c2 with everything removed
+    byte[] getNewClassData(String name) {
+        return InMemoryJavaCompiler.compile("p2.c2", "package p2; public class c2 { }");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/ClassUnload/SuperDependsTest.java	Thu Nov 08 18:33:43 2018 +0000
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test SuperDependsTest
+ * @bug 8210094
+ * @summary Create ClassLoader dependency from initiating loader to class loader through subclassing
+ * @modules java.base/jdk.internal.misc
+ *          java.compiler
+ * @library /testlibrary /testlibrary/whitebox /runtime/testlibrary
+ * @build sun.hotspot.WhiteBox
+ * @compile p2/c2.java MyDiffClassLoader.java
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SuperDependsTest
+ */
+import sun.hotspot.WhiteBox;
+import p2.*;
+
+public class SuperDependsTest {
+    public static WhiteBox wb = WhiteBox.getWhiteBox();
+    public static final String MY_TEST = "SuperDependsTest$c1s";
+
+
+    // p2.c2 loads through super class and creates dependency
+    public static class c1s extends p2.c2 {
+
+        private void test() throws Exception {
+            method2();
+        }
+
+        public c1s () throws Exception {
+            test();
+            ClassUnloadCommon.triggerUnloading();  // should not unload anything
+            test();
+        }
+    }
+
+    public void test() throws Throwable {
+
+        // now use the same loader to load class MyTest
+        Class MyTest_class = new MyDiffClassLoader(MY_TEST).loadClass(MY_TEST);
+
+        // Call MyTest to load p2.c2 twice and call p2.c2.method2
+        MyTest_class.newInstance();
+        ClassUnloadCommon.triggerUnloading();  // should not unload anything
+        ClassUnloadCommon.failIf(!wb.isClassAlive(MY_TEST), "should not be unloaded");
+        ClassUnloadCommon.failIf(!wb.isClassAlive("p2.c2"), "should not be unloaded");
+        // Unless MyTest_class is referenced here, the compiler can unload it.
+        System.out.println("Should not unload anything before here because " + MyTest_class + " is still alive.");
+    }
+
+    public static void main(String args[]) throws Throwable {
+        SuperDependsTest d = new SuperDependsTest();
+        d.test();
+        ClassUnloadCommon.triggerUnloading();  // should not unload anything
+        System.out.println("Should unload MyTest and p2.c2 just now");
+        ClassUnloadCommon.failIf(wb.isClassAlive(MY_TEST), "should be unloaded");
+        ClassUnloadCommon.failIf(wb.isClassAlive("p2.c2"), "should be unloaded");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/ClassUnload/p2/c2.java	Thu Nov 08 18:33:43 2018 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package p2;
+
+public class c2 {
+    int i;
+    public void method2() { i = 5; System.out.println("c2 method2 called"); }
+}