RFR: 8296656: java.lang.NoClassDefFoundError exception on running fully legitimate code [v7]

David Alayachew duke at openjdk.org
Fri Apr 21 15:50:59 UTC 2023


On Sat, 25 Mar 2023 22:08:23 GMT, Archie L. Cobbs <duke at openjdk.org> wrote:

>> This bug and a few others fall into the "output file clash" bucket. This is when the compiler thinks it's writing out two separate files, but due to the way the O/S 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 a `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.
>> 
>> It's infeasible to truly "fix" this problem, so we resort here to a salve, which is to add a new compiler flag `--detect-output-file-clashes` that enables detection of output file clashes. When the flag is enabled, and a clash is detected, an error is immediately thrown. For example, compiling the example above gives this:
>> 
>> $ javac --help-extra
>>   ...
>>   --detect-output-file-clashes
>>         Generate an error if any output file is overwritten during compilation. This can occur, for example,
>>         on case-insensitive filesystems. This applies to class files, native header files, and source files.
>>   ...
>> $ javac --detect-output-file-clashes Test.java
>> Test.java:4: error: error while writing Café: output file clash: /Users/archie/test/Test$Café.class
>>     interface Caf\u00e9 {
>>     ^
>> 1 error
>> 
>> This at least gives people at risk of encountering this problem a way to turn a runtime error into a compile-time error.
>> 
>> **Outstanding Questions**
>> * Is making this optional via an (extended) flag `--detect-output-file-clashes` the best way to address this?
>> * Does the new field `BaseFileManager.outputFilesWritten` ever need to be cleared? Can the file manager be used for multiple compilations? If so, is there some "reset" step we should hook into?
>
> Archie L. Cobbs has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Add "compiler.warn.output.file.clash" to message example exclusion file.

> > What's the best way I should go about testing this?
> 
> Using whatever your original example was. Or some simple example like this on a case-insensitive filesystem:
> 
> ```java
> public class Test {
>     interface Inner {
>     }
>     interface INNER {
>     }
> }
> ```
> 
> > I see instructions on how to build the JDK from the source code. Is that the best way?
> 
> As far as I know that's the best way... but I could be unaware of pre-built preview images somewhere.

Ok, beautiful. I'll get on that now. Thanks again to you both!

-------------

PR Comment: https://git.openjdk.org/jdk/pull/12754#issuecomment-1518022625


More information about the compiler-dev mailing list