8166203: NoClassDefFoundError should not be thrown if class is in_error_state at link time
authoriklam
Thu, 20 Oct 2016 13:41:07 -0700
changeset 42031 55dc92f033b9
parent 42029 73e8eed6e85d
child 42032 b6347ec083d8
8166203: NoClassDefFoundError should not be thrown if class is in_error_state at link time Reviewed-by: coleenp, dholmes, sspitsyn
hotspot/src/share/vm/oops/instanceKlass.cpp
hotspot/test/runtime/lambda-features/InterfaceInitializationStates.java
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Oct 20 16:53:39 2016 +0300
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Oct 20 13:41:07 2016 -0700
@@ -517,12 +517,14 @@
 
 bool InstanceKlass::link_class_impl(
     instanceKlassHandle this_k, bool throw_verifyerror, TRAPS) {
-  // check for error state.
-  // This is checking for the wrong state.  If the state is initialization_error,
-  // then this class *was* linked.  The CDS code does a try_link_class and uses
-  // initialization_error to mark classes to not include in the archive during
-  // DumpSharedSpaces.  This should be removed when the CDS bug is fixed.
-  if (this_k->is_in_error_state()) {
+  if (DumpSharedSpaces && this_k->is_in_error_state()) {
+    // This is for CDS dumping phase only -- we use the in_error_state to indicate that
+    // the class has failed verification. Throwing the NoClassDefFoundError here is just
+    // a convenient way to stop repeat attempts to verify the same (bad) class.
+    //
+    // Note that the NoClassDefFoundError is not part of the JLS, and should not be thrown
+    // if we are executing Java code. This is not a problem for CDS dumping phase since
+    // it doesn't execute any Java code.
     ResourceMark rm(THREAD);
     THROW_MSG_(vmSymbols::java_lang_NoClassDefFoundError(),
                this_k->external_name(), false);
--- a/hotspot/test/runtime/lambda-features/InterfaceInitializationStates.java	Thu Oct 20 16:53:39 2016 +0300
+++ b/hotspot/test/runtime/lambda-features/InterfaceInitializationStates.java	Thu Oct 20 13:41:07 2016 -0700
@@ -88,9 +88,7 @@
     // Iunlinked is testing initialization like interface I, except interface I is linked when
     // ClassLIM is linked.
     // Iunlinked is not linked already when K gets an initialization error.  Linking Iunlinked
-    // should succeed and not get NoClassDefFoundError because it does not depend on the
-    // initialization state of K for linking.  There's bug now where it gets this error.
-    // See: https://bugs.openjdk.java.net/browse/JDK-8166203.
+    // should succeed because it does not depend on the initialization state of K for linking.
     interface Iunlinked extends K {
         boolean v = InterfaceInitializationStates.out(Iunlinked.class);
     }
@@ -157,15 +155,9 @@
             System.out.println("ExceptionInInitializerError as expected");
         }
 
-        // Initialize Iunlinked. This should not get NoClassDefFoundError because K
+        // Initialize Iunlinked. No exception should be thrown even if K
         // (its super interface) is in initialization_error state.
-        // This is a bug.  It does now.
-        try {
-            boolean bb = Iunlinked.v;
-            throw new RuntimeException("FAIL exception not thrown for Iunlinked initialization");
-        } catch(NoClassDefFoundError e) {
-            System.out.println("NoClassDefFoundError thrown because of bug");
-        }
+        boolean bb = Iunlinked.v;
 
         // This should be okay
         boolean value = Iparams.v;
@@ -182,7 +174,7 @@
 
          // Check expected class initialization order
         List<Class<?>> expectedCInitOrder = Arrays.asList(L.class, K.class, M.class, ClassM.class,
-                                                          I.class, Iparams.class,
+                                                          I.class, Iunlinked.class, Iparams.class,
                                                           ClassIparams.class);
         if (!cInitOrder.equals(expectedCInitOrder)) {
             throw new RuntimeException(