RFR: 7016187: `javac -h` could generate conflict .h for inner class and class name with '_'

Jonathan Gibbons jonathan.gibbons at oracle.com
Fri Feb 24 02:24:09 UTC 2023


On 2/17/23 5:22 PM, Archie L. Cobbs wrote:
> On Thu, 16 Feb 2023 17:49:00 GMT, Archie L. Cobbs <duke at openjdk.org> wrote:
>
>> Consider these two classes:
>>
>> public class Foo_Bar {
>>      public static native void method();
>> }
>>
>>
>> public class Foo {
>>      public static class Bar {
>>          public static native void method();
>>      }
>> }
>>
>> If you run `javac -h` to generate native header files, classes `Foo_Bar` and `Foo$Bar` will want to generate the same native header file `Foo_Bar.h`.
>>
>> Currently, javac does not detect this situation, so in effect you get a "last writer wins" situation.
>>
>> This patch causes compilation to fail instead in this case with an error like this:
>>
>> Foo.java:2: error: error while writing Bar: native header file collision between Foo_Bar and Foo$Bar (both generate Foo_Bar.h)
>>      public static class Bar {
>>                    ^
>> 1 error
>> The JBS issue lists two problem cases, of which this PR addresses one.
> Thanks for the heads-up on that, admittedly I had totally forgotten about it. However I'm not sure whether there is anything to do beyond what's already being done to flag the filename conflict.
>
> The second problem (as I understand it) is that the two header files will include C macro definitions for `static final` constants that end up having the same name. For example, if `Foo$Bar` has a `public static final int field = 123` and `Foo_Bar` has a `public static final int field = 456`, then one header file will have:
>
> #undef Foo_Bar_field
> #define Foo_Bar_field 123L
>
> and the other will have:
>
> #undef Foo_Bar_field
> #define Foo_Bar_field 456L
>
> But notice the JNI version of the class names (`Foo_Bar`) is a prefix of the macro name (`Foo_Bar_field`) and also the name of the header file (`Foo_Bar.h`) minus the `.h`. So it's not possible to have two field macro symbols conflict this way without there already being a header file conflict, and therefore the current changes will detect these field conflicts as well as a side-effect. Put another way, the field name conflicts are just a side-effect of the JNI class name conflicts.
>
> Of course (and this is going beyond the reported bug) you could also have a field name conflict where the header file names don't conflict. For example:
>
> public class Foo {
>      public static final int Bar_field = 123;
> }
> public class Foo_Bar {
>      public static final int field = 456;
> }
>
> and so you'd generate two different header files (with different names) that both define `Foo_Bar_field`:
>
> #undef Foo_Bar_field
> #define Foo_Bar_field 123L
>
>
> #undef Foo_Bar_field
> #define Foo_Bar_field 456L
>
> But then you can still deal with it at the C/C++ level by including the headers in the right order, or including only one in each of two separate C/C++ files, etc. Yes, you would have to "know what you're doing" but I don't think there's enough justification for turning this case into an error at the javac compiler level. And in any case if you're writing JNI, you probably "know what you're doing" :)


Yeah, maybe the file-name conflict is enough. And as for JNI, Panama and 
jextract may be the way of the future.

-- Jon


>
> -------------
>
> PR: https://git.openjdk.org/jdk/pull/12602


More information about the compiler-dev mailing list