On Fri, 18 Sep 2026 14:21:52 GMT, Jorn Vernee <[email protected]> wrote:
>> Consider this set of classes:
>>
>>
>> interface I1 { void m(); }
>> interface I2 { void m(); }
>>
>>
>> class Widget implements I1 { // version 1
>> @Override
>> public void m() {}
>> }
>>
>>
>> class Widget implements I2 { // version 2
>> @Override
>> public void m() {}
>> }
>>
>>
>> The current jar tool validator, which checks if different versions of a
>> class in a multi-release jar file have the same API, will accept the above
>> two versions of `Widget` as valid, given that they both have a method called
>> `m` with the same signature.
>>
>> However, when version 2 of the Widget class is loaded by code that was
>> compiled against version 1, we can run into problems:
>>
>>
>> I1 x = new Widget(); // 1
>> System.out.println(x instanceof I1); // 2
>> x.m(); // 3
>>
>>
>> Depending on the implementation of the verifier, the assignment on line (1)
>> will succeed and cause heap pollution. The print statement on line (2) will
>> print `false`, even though the type of `x` is `I1`, and the method call on
>> line (3) will fail with an `IncompatibleClassChangeError`.
>>
>> Clearly, version 1 and 2 of the `Widget` class are incompatible, but the
>> current jar file validator doesn't catch this because it ignores super
>> interfaces.
>>
>> This patch adds a check for the super interfaces of a type to the validator
>> as well, to catch cases like these.
>>
>> ---------
>> - [x] I confirm that I make this contribution in accordance with the
>> [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai).
>
> Jorn Vernee has updated the pull request incrementally with one additional
> commit since the last revision:
>
> Add a few more test cases
Marked as reviewed by liach (Reviewer).
src/jdk.jartool/share/classes/sun/tools/jar/FingerPrint.java line 184:
> 182: cm.thisClass().asInternalName(),
> 183:
> cm.superclass().map(ClassEntry::asInternalName).orElse(null),
> 184:
> cm.interfaces().stream().map(ClassEntry::asInternalName).collect(Collectors.toSet()),
I think we can require the interfaces to be in the same order given we are
already strict. Using a List also makes the other parts of tracking simpler.
-------------
PR Review: https://git.openjdk.org/jdk/pull/32787#pullrequestreview-5248126267
PR Review Comment: https://git.openjdk.org/jdk/pull/32787#discussion_r4044233041