JIT-compiled code induces persistent NoClassDefFoundError during StackOverflow recovery, violating semantic consistency with Interpreter.

XMLWordPrintable

      ADDITIONAL SYSTEM INFORMATION :
      - Operating system: Linux
      - Compiler/toolchain: GCC 9.5
      - Source commit: 76b626867f7c436e493566c2cc5d6ac847420894 (tag: 1.8.0_492-internal, branch: master)
      - Build type: fastdebug (also happens in release version)
      - Coverage: enabled (built with --enable-coverage)
      - Build environment: Linux, compiled from source with GCC 9.5
      - Also happens in 1.8.0_472, released version

      A DESCRIPTION OF THE PROBLEM :
      A small Java program that:
      - Recursively calls a method until StackOverflowError occurs.
      - Catches Throwable in the recursive caller.
      - Assigns a float local (initialized to Float.MIN_VALUE) to a static string via String.valueOf after the catch.

      When run with -Xcomp or -Xmixed, the JVM prints NoClassDefFoundError. When run with -Xint, it prints OK as expected. This suggests a JIT compiler/runtime bug in exception/stack overflow handling and/or interaction with float locals and String.valueOf/Float.toString.

      The provided reproduction triggers a critical semantic violation where JIT-compiled execution (-Xcomp/-Xmixed) fails with a spurious NoClassDefFoundError during StackOverflowError recovery involving float operations, contradicting the correct behavior observed in -Xint mode. While physical stack frame usage inherently varies between execution tiers, the JVM is obligated to provide a consistent abstract machine view; the JIT compiler fails to ensure sufficient stack reservation (via adequate stack banging) for critical class resolution during unwinding, thereby allowing implementation details to corrupt class states. This divergence breaks the guarantee of functional equivalence across optimization levels, as the runtime must ensure that compiled code handles exception boundaries without introducing catastrophic state corruption absent in the interpreter.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1) Save the following source as Test.java.
      2) Compile: javac Test.java
      3) Run:
         - java -Xcomp -Xbatch Test
         - java -Xmixed -Xbatch Test
         - java -Xint -Xbatch Test

      ---------- BEGIN SOURCE ----------

      public class Test {

          public static String str = "";

          public static void main(java.lang.String[] args) {
              try {
                  new Test().run();
                  System.out.println("OK");
              } catch (java.lang.Throwable ex) {
                  System.out.println(ex.getClass().getCanonicalName());
              }
          }
          
          public void run() {
              float floatVar = Float.MIN_VALUE;
              try {
                  run();
              } catch (java.lang.Throwable t) {
              }
              str = String.valueOf(floatVar);
          }

      }


      ---------- END SOURCE ----------

      FREQUENCY :
      ALWAYS

            Assignee:
            Unassigned
            Reporter:
            Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: