Diagnostic.getEndPosition can throw an NPE with typical broken code

XMLWordPrintable

    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      java -version:
      openjdk version "26-beta" 2026-03-17
      OpenJDK Runtime Environment Temurin-26+21-202510232033 (build 26-beta+21-ea)
      OpenJDK 64-Bit Server VM Temurin-26+21-202510232033 (build 26-beta+21-ea, mixed mode, sharing)

      A DESCRIPTION OF THE PROBLEM :
      On JDK 26 EAs, calling javax.tools.Diagnostic.getEndPosition in a javax.tools.DiagnosticListener can result in a NullPointerException, attached as "Actual Result" below. This should not happen, like on 25 or earlier.

      REGRESSION : Last worked in version 25.0.1

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Put the test case code in `CustomDiagnosticCompiler.java` and run `java CustomDiagnosticCompiler.java`.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The output on 25 was "diagnostic end pos: 33"

      I'm not sure if it should be 33 or not, but I would expect it to at least not throw and return Diagnostic.NOPOS instead.
      ACTUAL -
      Exception in thread "main" java.lang.RuntimeException: java.lang.NullPointerException: Cannot invoke "com.sun.tools.javac.tree.EndPosTable.getEndPos(com.sun.tools.javac.tree.JCTree)" because "endPosTable" is null
      at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.invocationHelper(JavacTaskImpl.java:168)
      at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:100)
      at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:94)
      at CustomDiagnosticCompiler.main(CustomDiagnosticCompiler.java:24)
      Caused by: java.lang.NullPointerException: Cannot invoke "com.sun.tools.javac.tree.EndPosTable.getEndPos(com.sun.tools.javac.tree.JCTree)" because "endPosTable" is null
      at jdk.compiler/com.sun.tools.javac.tree.TreeInfo.getEndPos(TreeInfo.java:646)
      at jdk.compiler/com.sun.tools.javac.tree.JCTree.getEndPosition(JCTree.java:518)
      at jdk.compiler/com.sun.tools.javac.util.JCDiagnostic.getIntEndPosition(JCDiagnostic.java:750)
      at jdk.compiler/com.sun.tools.javac.util.JCDiagnostic.getEndPosition(JCDiagnostic.java:765)
      at jdk.compiler/com.sun.tools.javac.api.ClientCodeWrapper$DiagnosticSourceUnwrapper.getEndPosition(ClientCodeWrapper.java:827)
      at CustomDiagnosticCompiler.lambda$main$0(CustomDiagnosticCompiler.java:20)
      at jdk.compiler/com.sun.tools.javac.api.ClientCodeWrapper$WrappedDiagnosticListener.report(ClientCodeWrapper.java:784)
      at jdk.compiler/com.sun.tools.javac.util.Log.writeDiagnostic(Log.java:1008)
      at jdk.compiler/com.sun.tools.javac.util.Log$DefaultDiagnosticHandler.reportReady(Log.java:974)
      at jdk.compiler/com.sun.tools.javac.util.Log$DiagnosticHandler.reportWithLint(Log.java:190)
      at jdk.compiler/com.sun.tools.javac.util.Log$DiagnosticHandler.report(Log.java:162)
      at jdk.compiler/com.sun.tools.javac.util.Log.report(Log.java:837)
      at jdk.compiler/com.sun.tools.javac.util.AbstractLog.error(AbstractLog.java:125)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.reportSyntaxError(JavacParser.java:502)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.syntaxError(JavacParser.java:466)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.syntaxError(JavacParser.java:460)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.syntaxError(JavacParser.java:456)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.illegal(JavacParser.java:541)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.illegal(JavacParser.java:548)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.term3(JavacParser.java:1772)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.term2(JavacParser.java:1213)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.term1(JavacParser.java:1184)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.term(JavacParser.java:1140)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.term(JavacParser.java:1120)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.unannotatedType(JavacParser.java:1100)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.unannotatedType(JavacParser.java:1096)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.parseType(JavacParser.java:1072)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.parseType(JavacParser.java:1068)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.parseType(JavacParser.java:1063)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.classDeclaration(JavacParser.java:4393)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.classOrRecordOrInterfaceOrEnumDeclaration(JavacParser.java:4356)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.typeDeclaration(JavacParser.java:4345)
      at jdk.compiler/com.sun.tools.javac.parser.JavacParser.parseCompilationUnit(JavacParser.java:4141)
      at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.parse(JavaCompiler.java:662)
      at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.parse(JavaCompiler.java:638)
      at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.parse(JavaCompiler.java:700)
      at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.parseFiles(JavaCompiler.java:1046)
      at jdk.compiler/com.sun.tools.javac.main.JavaCompiler$InitialFileParser.parse(JavaCompiler.java:2044)
      at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.parseFiles(JavaCompiler.java:1033)
      at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:955)
      at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:104)
      at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.invocationHelper(JavacTaskImpl.java:152)
      at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:100)
      at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:94)
      at CustomDiagnosticCompiler.main(CustomDiagnosticCompiler.java:24)
      at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
      at java.base/java.lang.reflect.Method.invoke(Method.java:565)
      at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.execute(SourceLauncher.java:256)
      at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.run(SourceLauncher.java:138)
      at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.main(SourceLauncher.java:76)

      ---------- BEGIN SOURCE ----------
      import javax.tools.JavaFileObject;
      import javax.tools.SimpleJavaFileObject;
      import javax.tools.ToolProvider;

      void main() {
          SimpleJavaFileObject fileObject = new SimpleJavaFileObject(
              URI.create("string:///BrokenClass.java"), JavaFileObject.Kind.SOURCE
          ) {
              @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) {
                  return """
                         public class BrokenClass extends {
                         }
                         """;
              }
          };
          ToolProvider.getSystemJavaCompiler().getTask(
              null,
              null,
              diagnostic -> System.out.println("diagnostic end pos: " + diagnostic.getEndPosition()),
              null,
              null,
              List.of(fileObject)
          ).call();
      }
      ---------- END SOURCE ----------

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

              Created:
              Updated: