jshell ClassFormatError when making inner class static

XMLWordPrintable

    • Type: CSR
    • Resolution: Unresolved
    • Priority: P4
    • 26
    • Component/s: tools
    • None
    • minimal
    • A new lint warning will be produced in cases that often lead to very weird behavior currently.
    • add/remove/modify command line option
    • JDK

      Summary

      A new warning is produced when static-ness of a class recorded in an InnerClasses attribute is not matching the static-ness of the same-named class read from source.

      Problem

      Consider these three files:

      OriginalVersion.java:
      class Test {
          public class Nested {}
      }
      
      Use.java:
      public class Use {
          Test.Nested n;
      }
      
      Test.java:
      class Test {
          Use use;
          public static class Nested {}
      }
      

      First compiling OriginalVersion.java and Use.java:

      $ ~/tools/jdk/jdk-25/bin/javac -d out OriginalVersion.java Use.java 
      

      this will record the Test.Nested as a non-static innerclass inside the InnerClasses attribute of Use. Then compiling Test.java with the classfile on classpath leads to:

      $ ~/tools/jdk/jdk-25/bin/javac -classpath out Test.java 
      An exception has occurred in the compiler (25-internal). Please file a bug against the Java compiler via the Java bug reporting page (https://bugreport.java.com) after checking the Bug Database (https://bugs.java.com) for duplicates. Include your program, the following diagnostic, and the parameters passed to the Java compiler in your report. Thank you.
      java.lang.NullPointerException: Cannot read field "sym" because "mdef.params.head" is null
              at jdk.compiler/com.sun.tools.javac.comp.Lower.visitClassDef(Lower.java:2240)
              at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:859)
              at jdk.compiler/com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
              at jdk.compiler/com.sun.tools.javac.comp.Lower.translate(Lower.java:2062)
              at jdk.compiler/com.sun.tools.javac.comp.Lower.visitClassDef(Lower.java:2204)
              at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:859)
              at jdk.compiler/com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
              at jdk.compiler/com.sun.tools.javac.comp.Lower.translate(Lower.java:2062)
              at jdk.compiler/com.sun.tools.javac.comp.Lower.translate(Lower.java:2081)
              at jdk.compiler/com.sun.tools.javac.comp.Lower.translateTopLevelClass(Lower.java:4366)
              at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.desugar(JavaCompiler.java:1688)
              at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.desugar(JavaCompiler.java:1505)
              at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:968)
              at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:319)
              at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:178)
              at jdk.compiler/com.sun.tools.javac.Main.compile(Main.java:66)
              at jdk.compiler/com.sun.tools.javac.Main.main(Main.java:52)
      printing javac parameters to: /tmp/javac.20251031_131057.args
      

      The reason is that when Use.class is read, it changes the flags of Test.Nested to a state that is incompatible with the actual source file being compiled.

      Solution

      The solution is twofold:

      • while reading the InnerClasses attribute, javac will ignore the flags for classes that are being read from the source file

      • javac will produce a new warning under the -Xlint:classfile category:

        $ javac -classpath out -Xlint:classfile Test.java warning: [classfile] InnerClasses attribute for Nested in out/Use.class inconsistent with source code 1 warning

      Specification

      There will be a new warning under the -Xlint:classfile category when a mismatch is detected between the static-ness recorded in an InnerClasses attribute and the static-ness in the source file.

      Please note the -Xlint:classfile is not enabled by default.

            Assignee:
            Jan Lahoda
            Reporter:
            Hannes Greule
            Maurizio Cimadamore
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated: