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

Add new lint flag "output-file-clash"

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 21
    • tools
    • None
    • behavioral
    • minimal
    • Hide
      Compiler behavior should be unchanged when the new flag is not used.

      Implicit checking from Xlint:all expected to be manageable.
      Show
      Compiler behavior should be unchanged when the new flag is not used. Implicit checking from Xlint:all expected to be manageable.
    • add/remove/modify command line option
    • Implementation

      Summary

      Add a new compiler lint flag output-file-clash that will enable detection of output file clashes. An output file clash is when the compiler writes two different output files, but due to the behavior of the filesystem these files end up being written to the same underlying filesystem file.

      Problem

      Sometimes the compiler thinks it's writing out two separate files, but due to the way the underlying filesystem maps Path's to actual files, it's really writing the same file twice.

      This is usually due to case-insensitive filesystems, but can also be due to how a filesystem "normalizes" file names. For example, on MacOS, compiling this class will generate such a clash:

      public class Test {
          interface Cafe\u0301 {
          }
          interface Caf\u00e9 {
          }
      }

      The reason is that \u0301 is the Unicode character "Combining Acute Accent" which means "stick an accent over the previous character". So MacOS normalizes the letter e followed by a \u0301 into a Unicode \u00e9, that is, é. However, the Java language treats these the two names Cafe\u0301 and Caf\u00e9 as distinct.

      Of course, on any case-insensitive filesystem a class like this would cause an output file clash for the file Test$Inner.class':

      public class Test {
          class Inner {
          }
          class INNER {
          }
      }

      Solution

      There's no way to avoid this problem without changing the way the compiler maps output files to filesystem filenames, which would be too disruptive.

      So the solution here is to simply provide a way for people experiencing this problem to convert what is currently a runtime error into a compile-time warning (or error with -Werror). This is by adding a new lint flag output-file-clash that enables output file clash detection. The term "output file" covers class files, source files, and native header files.

      If the flag is not used, then the compiler should behave exactly as it currently does. Therefore, there should be no backward compatibility risk.

      An alternative, a more aggressive approach would be to always enable this behavior and/or make it an error instead of a warning.

      Specification

      New addition to "javac --help-lint":

      output-file-clash
          Warn when an output file is overwritten during compilation. This can occur, for example,
          on case-insensitive filesystems. Covers class files, native header files, and source files.

      An example of the new warning:

      $ javac -Xlint:output-file-clash Test.java
      warning: [output-file-clash] output file written more than once: /Users/archie/test/Test$Café.class
      1 warning

            acobbs Archie Cobbs
            webbuggrp Webbug Group
            Vicente Arturo Romero Zaldivar
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: