Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8166203

NoClassDefFoundError should not be thrown if class is in_error_state at link time

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 10
    • 9
    • hotspot


        For the case where a class has an initialization error, the class is already linked so this code is wrong in link_class_impl:

          // check for error state. This is checking for the wrong state.
          // If initialization_error, then this class *was* linked.
          if (this_k->is_in_error_state()) {
            ResourceMark rm(THREAD);
            THROW_MSG_(vmSymbols::java_lang_NoClassDefFoundError(),
                       this_k->external_name(), false);
          }

        There is nothing in the spec that says to throw NCDFE for link time exceptions. This also prevents linking interfaces that extend interfaces that have had initialization errors, which is also legal in the spec. In the JLS 12.4.2 step 7, implies that initialization errors in interfaces do not affect other interfaces. Linking interfaces should not be dependent on initialization state either (there's nothing in the spec about this).

        Here's a test program that demonstrates this.

        --- begin source ---
        class Test {
            static Object someMethod() { throw new RuntimeException("initialization_error"); }
            static boolean out(String s) { System.out.println(s); return true; }

            // K interface with a default method has an initialization error
            interface K {
                static final Object CONST = someMethod();
                default int method() { return 2; }
            }

            // Iunlinked is not linked when K gets an initialization error. Linking Iunlinked should not
            // get NoClassDefFoundError because it does not depend on the initialization state of K for
            // linking. There's bug now where it does, filed separately.
            interface Iunlinked extends K {
                boolean v = out("Iunlinked");
            }

          static class C implements K {}

          public static void main(java.lang.String[] unused) {
              try {
                  C c = new C();
              } catch (ExceptionInInitializerError e) {
                  System.out.println("this is expected");
              }
              boolean b = Iunlinked.v; // should not fail!
          }
        }
        --- end source ---

        I tested the jvm with removing the code above and everything passes, except CDS uses initialization_error state for some purpose that I can't unwind right now. See linked bug for more.

        Suggested fix is to create a state < linked and use this in the CDS code. You can't use initialization_error.

              iklam Ioi Lam
              coleenp Coleen Phillimore
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Created:
                Updated:
                Resolved: