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

JavacFiler.checkFileReopening drowns in exceptions after Modular Runtime Images change

XMLWordPrintable

    • b149
    • Not verified

      The easiest way to reproduce is to build some annotation-processing-heavy project, like JMH:

      $ hg clone http://hg.openjdk.java.net/code-tools/jmh/ jmh
      $ cd jmh
      $ mvn clean install -pl jmh-core-it -DskipTests

      Time to compile:
        jdk9b111: 18.979 s
        8u66: 6.426 s

      Massive regression! Profiling jdk9b111 case yields this very hot branch:
       | +- 10.080 (9%) org.openjdk.jmh.generators.annotations.APGeneratorDestinaton.newClass(java.lang.String)
       | | +- 10.060 (9%) com.sun.tools.javac.processing.JavacFiler.createSourceFile(java.lang.CharSequence, javax.lang.model.element.Element[])
       | | | +- 10.060 (9%) com.sun.tools.javac.processing.JavacFiler.createSourceOrClassFile(boolean, java.lang.String)
       | | | +- 10.030 (9%) com.sun.tools.javac.processing.JavacFiler.checkFileReopening(javax.tools.FileObject, boolean)
       | | | | +- 9.990 (8%) com.sun.tools.javac.file.JavacFileManager.isSameFile(javax.tools.FileObject, javax.tools.FileObject)
       | | | | | +- 9.990 (8%) com.sun.tools.javac.file.PathFileObject.isSameFile(com.sun.tools.javac.file.PathFileObject)
       | | | | | +- 9.990 (8%) java.nio.file.Files.isSameFile(java.nio.file.Path, java.nio.file.Path)
       | | | | | +- 9.990 (8%) sun.nio.fs.UnixFileSystemProvider.isSameFile(java.nio.file.Path, java.nio.file.Path)
       | | | | | +- 7.080 (6%) sun.nio.fs.UnixFileAttributes.get(sun.nio.fs.UnixPath, boolean)
       | | | | | | +- 7.080 (6%) sun.nio.fs.UnixNativeDispatcher.stat(sun.nio.fs.UnixPath, sun.nio.fs.UnixFileAttributes)
       | | | | | | +- 6.700 (6%) sun.nio.fs.UnixNativeDispatcher.stat0(long, sun.nio.fs.UnixFileAttributes)
       | | | | | | | +- 2.750 (2%) sun.nio.fs.UnixException.<init>(int)
       | | | | | | | +- 2.750 (2%) java.lang.Exception.<init>()
       | | | | | | | +- 2.750 (2%) java.lang.Throwable.<init>()
       | | | | | | | +- 2.740 (2%) java.lang.Throwable.fillInStackTrace()
       | | | | | | | +- 2.740 (2%) java.lang.Throwable.fillInStackTrace(int)

      The relevant code is:

          private void checkFileReopening(FileObject fileObject, boolean addToHistory) throws FilerException {
              for (FileObject veteran : fileObjectHistory) {
                  if (fileManager.isSameFile(veteran, fileObject)) {
                      if (lint)
                          log.warning("proc.file.reopening", fileObject.getName());
                      throw new FilerException("Attempt to reopen a file for path " + fileObject.getName());
                  }
              }
              if (addToHistory)
                  fileObjectHistory.add(fileObject);
          }

      In other words, when doing isSameFile, we are stat0-ing the arguments, get the -1 error from stat if file does not exist, which throws an exception from native back to NIO to handle. Since checkFileReopening does the linear search through the history, if we *did not* yet created the fileObject, it does not exist, and we are getting all the exceptions for each comparison.

      A trivial change, adding the exists check in checkFileReopening:

          private void checkFileReopening(FileObject fileObject, boolean addToHistory) throws FilerException {
              if (fileObject instanceof PathFileObject) {
                  if (!Files.exists(((PathFileObject) fileObject).getPath())) {
                      if (addToHistory)
                          fileObjectHistory.add(fileObject);
                      return;
                  }
              }

      ...drops the compilation time back to almost normal levels: 7.946 s

            jlahoda Jan Lahoda
            shade Aleksey Shipilev
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: