From vromero at openjdk.org Sat Nov 1 12:25:47 2025 From: vromero at openjdk.org (Vicente Romero) Date: Sat, 1 Nov 2025 12:25:47 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v12] In-Reply-To: References: Message-ID: > Javac is throwing an OOME for the code like: > > class Test { > interface WithMixin01 {} > // ... > // 20 interfaces here > interface WithMixin20 {} > > interface ClientA extends > WithMixin02, > WithMixin01, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > interface ClientB extends > WithMixin01, > WithMixin02, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > public static void main(String... args) { > ClientA a = null; > ClientB b = null; > String selector = "a"; > Object o = switch (selector) { > case "a" -> a; > case "b" -> b; > default -> null; > }; > } > } > > the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very slooooow. > > TIA Vicente Romero has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 16 additional commits since the last revision: - Merge branch 'master' into JDK-8369654 - fixing comment - adding some doc - delta changes - simplifying code - adding more array support - missing supertype - another change - another fix - minor fixes - ... and 6 more: https://git.openjdk.org/jdk/compare/bc6df8bb...34e2d9d4 ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28050/files - new: https://git.openjdk.org/jdk/pull/28050/files/e5bfcfd1..34e2d9d4 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=11 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=10-11 Stats: 44514 lines in 404 files changed: 23137 ins; 18965 del; 2412 mod Patch: https://git.openjdk.org/jdk/pull/28050.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28050/head:pull/28050 PR: https://git.openjdk.org/jdk/pull/28050 From vromero at openjdk.org Sun Nov 2 02:19:19 2025 From: vromero at openjdk.org (Vicente Romero) Date: Sun, 2 Nov 2025 02:19:19 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy Message-ID: javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. This new visitor will compare types looking for exactness which is something desirable in a map key. TIA ------------- Commit messages: - 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy Changes: https://git.openjdk.org/jdk/pull/28101/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28101&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8337142 Stats: 96 lines in 2 files changed: 90 ins; 0 del; 6 mod Patch: https://git.openjdk.org/jdk/pull/28101.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28101/head:pull/28101 PR: https://git.openjdk.org/jdk/pull/28101 From mcimadamore at openjdk.org Mon Nov 3 10:06:23 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 10:06:23 GMT Subject: RFR: 8366196: Crash in AbstractMethodCheck.getMethodCheckFailure In-Reply-To: References: Message-ID: On Thu, 30 Oct 2025 16:47:56 GMT, Jan Lahoda wrote: > `AttrRecover` invokes `Attr.checkMethod` with a cached `CheckContext`. `checkMethod` may be calling `report` on the `CheckContext`: > https://github.com/openjdk/jdk/blob/ed36b9bb6f3d429db6accfb3b096e50e7f2217ff/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java#L4986 > > This fails if the cached `CheckContext` is a `MethodCheckContext`, whose `report` method throws. > > The proposal herein is to not delegate to the cached `CheckContext`'s `report` method, but rather always report the error using `Check.basicHandler`. Looks good! ------------- Marked as reviewed by mcimadamore (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28066#pullrequestreview-3410277978 From mcimadamore at openjdk.org Mon Nov 3 10:07:33 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 10:07:33 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v12] In-Reply-To: References: Message-ID: On Sat, 1 Nov 2025 12:25:47 GMT, Vicente Romero wrote: >> Javac is throwing an OOME for the code like: >> >> class Test { >> interface WithMixin01 {} >> // ... >> // 20 interfaces here >> interface WithMixin20 {} >> >> interface ClientA extends >> WithMixin02, >> WithMixin01, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> interface ClientB extends >> WithMixin01, >> WithMixin02, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> public static void main(String... args) { >> ClientA a = null; >> ClientB b = null; >> String selector = "a"; >> Object o = switch (selector) { >> case "a" -> a; >> case "b" -> b; >> default -> null; >> }; >> } >> } >> >> the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very ... > > Vicente Romero has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 16 additional commits since the last revision: > > - Merge branch 'master' into JDK-8369654 > - fixing comment > - adding some doc > - delta changes > - simplifying code > - adding more array support > - missing supertype > - another change > - another fix > - minor fixes > - ... and 6 more: https://git.openjdk.org/jdk/compare/fc64c841...34e2d9d4 Very good -- thanks! ------------- Marked as reviewed by mcimadamore (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28050#pullrequestreview-3410285240 From mcimadamore at openjdk.org Mon Nov 3 11:05:05 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 11:05:05 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy In-Reply-To: References: Message-ID: <9K1ROatwdZUPPEA3TutMLsxam69WX-_y9HpFIjZfvbk=.7802fef6-b1ec-47c5-80da-83aae4b29ae9@github.com> On Sun, 2 Nov 2025 02:12:40 GMT, Vicente Romero wrote: > javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: > > - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType > - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop > > The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. > > This new visitor will compare types looking for exactness which is something desirable in a map key. > > TIA Question: what if containsTypeEquivalent is defined in terms of containsTypeRecursive? Won't the cache then prevent the SOE? ------------- PR Comment: https://git.openjdk.org/jdk/pull/28101#issuecomment-3479961463 From mcimadamore at openjdk.org Mon Nov 3 11:20:03 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 11:20:03 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy In-Reply-To: <9K1ROatwdZUPPEA3TutMLsxam69WX-_y9HpFIjZfvbk=.7802fef6-b1ec-47c5-80da-83aae4b29ae9@github.com> References: <9K1ROatwdZUPPEA3TutMLsxam69WX-_y9HpFIjZfvbk=.7802fef6-b1ec-47c5-80da-83aae4b29ae9@github.com> Message-ID: On Mon, 3 Nov 2025 11:02:41 GMT, Maurizio Cimadamore wrote: > Question: what if containsTypeEquivalent is defined in terms of containsTypeRecursive? Won't the cache then prevent the SOE? This seems to fix the SOE -- but it introduces some spurious errors in the build... maybe worth more investigation? E.g. it almost seems as if javac kind of relies on cycles not to be detected... ------------- PR Comment: https://git.openjdk.org/jdk/pull/28101#issuecomment-3480014278 From amaembo at gmail.com Mon Nov 3 11:32:47 2025 From: amaembo at gmail.com (Tagir Valeev) Date: Mon, 3 Nov 2025 12:32:47 +0100 Subject: Type-use annotation on var lambda parameter Message-ID: Hello! I stumbled on the following issue. Let's consider this Java file: package com.example; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.function.Function; import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.RUNTIME; @Retention(value=RUNTIME) @Target(value={TYPE_USE}) @interface Anno { } public class TestClass { public static void main(String[] args) { Function f = (@Anno var val ) -> Integer.toHexString(val); System.out.println(f.apply(10)); } } As you can see, there's a TYPE_USE annotation which is applied to the lambda parameter declared with 'var' keyword. If I understand JLS 9.7.4 [1] correctly, this should not be legal: > If the annotation appears before a void method declaration or a variable declaration that uses var (?14.4, ?15.27.1), then there is no closest type. If the annotation's interface is deemed to apply only to the type which is closest to the annotation, a compile-time error occurs. However, javac accepts this code. I tried different versions between Java 11 and Java 25, and the result is the same: the file is compiled successfully. However, the TestClass.class file contains no references to the Anno annotation at all, despite it having the RUNTIME retention. So it looks like the annotation is silently ignored. One thing that confuses me is that the Eclipse compiler (ecj-4.34.jar) also accepts this code. However, it generates a RuntimeVisibleTypeAnnotations attribute for the Anno annotation. So either both compilers accept this code incorrectly, or my understanding of the specification is wrong. Could you please take a look at the javac issue? I'd be happy to be corrected if I misunderstood the specification. Thank you in advance! Tagir Valeev [1] https://docs.oracle.com/javase/specs/jls/se25/html/jls-9.html#jls-9.7.4 -------------- next part -------------- An HTML attachment was scrubbed... URL: From jlahoda at openjdk.org Mon Nov 3 11:44:12 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 3 Nov 2025 11:44:12 GMT Subject: Integrated: 8366196: Crash in AbstractMethodCheck.getMethodCheckFailure In-Reply-To: References: Message-ID: On Thu, 30 Oct 2025 16:47:56 GMT, Jan Lahoda wrote: > `AttrRecover` invokes `Attr.checkMethod` with a cached `CheckContext`. `checkMethod` may be calling `report` on the `CheckContext`: > https://github.com/openjdk/jdk/blob/ed36b9bb6f3d429db6accfb3b096e50e7f2217ff/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java#L4986 > > This fails if the cached `CheckContext` is a `MethodCheckContext`, whose `report` method throws. > > The proposal herein is to not delegate to the cached `CheckContext`'s `report` method, but rather always report the error using `Check.basicHandler`. This pull request has now been integrated. Changeset: 15fd5292 Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/15fd52925ab64a6a9e33691eed9e952a7b75da4b Stats: 66 lines in 2 files changed: 64 ins; 0 del; 2 mod 8366196: Crash in AbstractMethodCheck.getMethodCheckFailure Reviewed-by: liach, mcimadamore ------------- PR: https://git.openjdk.org/jdk/pull/28066 From mcimadamore at openjdk.org Mon Nov 3 11:47:02 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 11:47:02 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy In-Reply-To: References: <9K1ROatwdZUPPEA3TutMLsxam69WX-_y9HpFIjZfvbk=.7802fef6-b1ec-47c5-80da-83aae4b29ae9@github.com> Message-ID: On Mon, 3 Nov 2025 11:17:32 GMT, Maurizio Cimadamore wrote: > > Question: what if containsTypeEquivalent is defined in terms of containsTypeRecursive? Won't the cache then prevent the SOE? > > This seems to fix the SOE -- but it introduces some spurious errors in the build... maybe worth more investigation? E.g. it almost seems as if javac kind of relies on cycles not to be detected... Nah... it seems to me that `containsTypeRecursive` never sees the same type pair twice in a nested context. We keep adding newer type to the type cache, but it seems like the program is running away here... ------------- PR Comment: https://git.openjdk.org/jdk/pull/28101#issuecomment-3480108251 From mcimadamore at openjdk.org Mon Nov 3 11:50:01 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 11:50:01 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy In-Reply-To: References: <9K1ROatwdZUPPEA3TutMLsxam69WX-_y9HpFIjZfvbk=.7802fef6-b1ec-47c5-80da-83aae4b29ae9@github.com> Message-ID: On Mon, 3 Nov 2025 11:44:08 GMT, Maurizio Cimadamore wrote: > > > Question: what if containsTypeEquivalent is defined in terms of containsTypeRecursive? Won't the cache then prevent the SOE? > > > > > > This seems to fix the SOE -- but it introduces some spurious errors in the build... maybe worth more investigation? E.g. it almost seems as if javac kind of relies on cycles not to be detected... > > Nah... it seems to me that `containsTypeRecursive` never sees the same type pair twice in a nested context. We keep adding newer type to the type cache, but it seems like the program is running away here... Your analysis in this PR seems to imply that the cycle occurs via TypePair::equals, but when debugging I don't see this method being invoked at all (I do see the hashCode method being invoked though). I think we need to characterize the nature of the recursion more precisely. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28101#issuecomment-3480123502 From jlahoda at openjdk.org Mon Nov 3 12:06:30 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 3 Nov 2025 12:06:30 GMT Subject: Integrated: 8370865: Incorrect parser error for compact source files and multi-variable declarations In-Reply-To: References: Message-ID: On Wed, 29 Oct 2025 13:51:09 GMT, Jan Lahoda wrote: > Consider code like: > > int f1, f2; > void main() {} > > > When javac's parser accepts `f1`, it sees `,`, but it won't parse this as top-level field declarations, failing with: > > /tmp/F.java:1: error: class, interface, annotation type, enum, record, method or field expected > int f1, f2; > ^ > 1 error > > > This PR changes the parser to also accept the `,` as the next token when parsing top-level fields. This pull request has now been integrated. Changeset: abf4f3da Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/abf4f3da76f413406de2860e4fbfacccfa15c221 Stats: 155 lines in 3 files changed: 153 ins; 0 del; 2 mod 8370865: Incorrect parser error for compact source files and multi-variable declarations Reviewed-by: vromero ------------- PR: https://git.openjdk.org/jdk/pull/28044 From mcimadamore at openjdk.org Mon Nov 3 13:09:45 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 13:09:45 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy In-Reply-To: References: Message-ID: On Sun, 2 Nov 2025 02:12:40 GMT, Vicente Romero wrote: > javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: > > - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType > - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop > > The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. > > This new visitor will compare types looking for exactness which is something desirable in a map key. > > TIA I did some more analysis. It seems like inference completes correctly. But at the last step we end up with a very complex type (for the type variable in List::of): M&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>,? extends java.lang.Object&Nine&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Six&Thirteen&Eleven&Thirteen&Eleven&Thirte en>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Six>> (!!) In the very last step of inference we have to check if this is a subtype of Object (the upper bound of the tvar). And this crashes javac, because subtyping needs to capture and capture triggers a glb involving this huge type which then consumes the stack. Eventually this computation ends up in `containsTypeRecursive` with these two types: T = Test.Ten&Test.Thirteen&Test.Eleven&Test.Thirteen>&Test.Thirteen>> S = Test.Ten&Test.Thirteen> At which point we keep looping forever because, to check if we have already seen this type pair, we need to perform (as you said), a nested containment check which brings us back here. So, we never decide whether we can add the type pair to the cache or not... So, your fix seems to be correct -- we need a simpler way to structurally compares two types w/o calling back into containment. src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 1350: > 1348: */ > 1349: SameTypeVisitor isSameTypeVisitor = new SameTypeVisitor(); > 1350: class SameTypeVisitor extends TypeRelation { I suggest to maybe make this an abstract class (with 2 abstract methods), then define `isSameTypeVisitor` as before, as an anonymous instance of our new abstract class, then define another equality visitor instance for type pair. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28101#issuecomment-3480424235 PR Review Comment: https://git.openjdk.org/jdk/pull/28101#discussion_r2486430939 From vromero at openjdk.org Mon Nov 3 14:56:30 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 3 Nov 2025 14:56:30 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy [v2] In-Reply-To: References: Message-ID: <3vyz4FHRvN1mJZm5wCNEtPYdczimn-ghxuoK3YxlT64=.ffa6608e-a725-4210-94d8-c6cd5693cdb2@github.com> > javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: > > - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType > - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop > > The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. > > This new visitor will compare types looking for exactness which is something desirable in a map key. > > TIA Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: addressing review comments ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28101/files - new: https://git.openjdk.org/jdk/pull/28101/files/21fab4d0..ef427b38 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28101&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28101&range=00-01 Stats: 20 lines in 1 file changed: 11 ins; 5 del; 4 mod Patch: https://git.openjdk.org/jdk/pull/28101.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28101/head:pull/28101 PR: https://git.openjdk.org/jdk/pull/28101 From vromero at openjdk.org Mon Nov 3 14:56:32 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 3 Nov 2025 14:56:32 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy [v2] In-Reply-To: References: Message-ID: On Mon, 3 Nov 2025 13:06:49 GMT, Maurizio Cimadamore wrote: >> Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: >> >> addressing review comments > > src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 1350: > >> 1348: */ >> 1349: SameTypeVisitor isSameTypeVisitor = new SameTypeVisitor(); >> 1350: class SameTypeVisitor extends TypeRelation { > > I suggest to maybe make this an abstract class (with 2 abstract methods), then define `isSameTypeVisitor` as before, as an anonymous instance of our new abstract class, then define another equality visitor instance for type pair. I updated the PR with this suggestion, thanks ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28101#discussion_r2486766423 From jlahoda at openjdk.org Mon Nov 3 14:51:36 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 3 Nov 2025 14:51:36 GMT Subject: RFR: 8359145: Implement JEP 530: Primitive Types in Patterns, instanceof, and switch (Fourth Preview) [v4] In-Reply-To: References: Message-ID: On Thu, 30 Oct 2025 12:50:14 GMT, Aggelos Biboudis wrote: >> PR for Primitive Types in Patterns, instanceof, and switch (Fourth Preview). >> >> spec: https://cr.openjdk.org/~abimpoudis/instanceof/latest/ > > Aggelos Biboudis has updated the pull request incrementally with one additional commit since the last revision: > > Fix regression in Check Looks OK to me. ------------- Marked as reviewed by jlahoda (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27637#pullrequestreview-3411387946 From jlahoda at openjdk.org Mon Nov 3 15:10:49 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 3 Nov 2025 15:10:49 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v4] In-Reply-To: References: Message-ID: > Consider code like: > > package test; > public class Test { > private int test(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > ``` > > This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > The goal of this PR is to improve the error, at least in some cases to something along these lines: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > missing patterns: > test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) > 1 error > > > The (very simplified) way it works in a recursive (or induction) way: > - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. > - for a current missing pattern, try to enhance it: > - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. > - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. > > This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. > > There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. > > Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. > > There's also an open possibility for select tools to delay the more detailed computation to some later time, although that would need to be tried and eval... Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 23 commits: - Merge branch 'JDK-8364991' into JDK-8367530 - Fixing tests - Merge branch 'JDK-8364991-2' into JDK-8367530-2 - Better visualisation. - Merge branch 'JDK-8367499' into JDK-8367530 - Merge branch 'JDK-8364991' into JDK-8367499 - Fixing tests. - Cleanup. - Cleanup. - Cleanup. - ... and 13 more: https://git.openjdk.org/jdk/compare/e6a3f0da...b7c33349 ------------- Changes: https://git.openjdk.org/jdk/pull/27256/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=03 Stats: 1326 lines in 15 files changed: 1233 ins; 43 del; 50 mod Patch: https://git.openjdk.org/jdk/pull/27256.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27256/head:pull/27256 PR: https://git.openjdk.org/jdk/pull/27256 From mcimadamore at openjdk.org Mon Nov 3 16:01:45 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 16:01:45 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy [v2] In-Reply-To: <3vyz4FHRvN1mJZm5wCNEtPYdczimn-ghxuoK3YxlT64=.ffa6608e-a725-4210-94d8-c6cd5693cdb2@github.com> References: <3vyz4FHRvN1mJZm5wCNEtPYdczimn-ghxuoK3YxlT64=.ffa6608e-a725-4210-94d8-c6cd5693cdb2@github.com> Message-ID: On Mon, 3 Nov 2025 14:56:30 GMT, Vicente Romero wrote: >> javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: >> >> - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType >> - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop >> >> The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. >> >> This new visitor will compare types looking for exactness which is something desirable in a map key. >> >> TIA > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > addressing review comments src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 3901: > 3899: boolean sameTypeArguments(List ts, List ss) { > 3900: while (ts.nonEmpty() && ss.nonEmpty() > 3901: && exactTypeVisitor.visit(ts.head, ss.head)) { You could delegate to `sameTypeComparator` here? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28101#discussion_r2487001792 From mcimadamore at openjdk.org Mon Nov 3 16:06:59 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 16:06:59 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy [v2] In-Reply-To: References: <3vyz4FHRvN1mJZm5wCNEtPYdczimn-ghxuoK3YxlT64=.ffa6608e-a725-4210-94d8-c6cd5693cdb2@github.com> Message-ID: On Mon, 3 Nov 2025 15:58:51 GMT, Maurizio Cimadamore wrote: >> Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: >> >> addressing review comments > > src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 3901: > >> 3899: boolean sameTypeArguments(List ts, List ss) { >> 3900: while (ts.nonEmpty() && ss.nonEmpty() >> 3901: && exactTypeVisitor.visit(ts.head, ss.head)) { > > You could delegate to `sameTypeComparator` here? Another possibility would be to declare an overloaded method to `isSameType` that takes a type argument comparator function. And maybe the default type argument comparator function is `containsTypeEquivalent` but then other clients could override that. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28101#discussion_r2487016381 From jlahoda at openjdk.org Mon Nov 3 16:19:27 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 3 Nov 2025 16:19:27 GMT Subject: RFR: 8370334: javadoc NPE with "import module" statement [v2] In-Reply-To: References: Message-ID: > `Modules.enter` completes all root modules, but in case of additional modules being added to the module graph via `Modules.addExtraAddModules` (either from javadoc, or using the `CompilationTask.addModules`, these extra modules may not be completed at this time. Normally, they are completed eventually, but if their `module-info`s contain `import module`, an NPE will appear while checking the import, before the complete happens. > > The proposal herein is to consistently complete all modules in the module graph when the module graphs is setup. Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Don't eagerly complete the unnamed module. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27974/files - new: https://git.openjdk.org/jdk/pull/27974/files/ff2162ee..14ac910e Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27974&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27974&range=00-01 Stats: 4 lines in 1 file changed: 3 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/27974.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27974/head:pull/27974 PR: https://git.openjdk.org/jdk/pull/27974 From jlahoda at openjdk.org Mon Nov 3 17:06:36 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 3 Nov 2025 17:06:36 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain In-Reply-To: References: Message-ID: On Thu, 4 Sep 2025 15:22:57 GMT, Archie Cobbs wrote: > When bit shifting an `int` or `long` value by an amount `X`, all but the last 5 or 6 (respectively) bits of `X` are ignored. > > This can create a trap for the unwary, as in this example: > > public long readLongBigEndian(byte[] buf, int offset) { > return ((buf[offset + 0] & 0xff) << 56) // BUG HERE > | ((buf[offset + 1] & 0xff) << 48) // BUG HERE > | ((buf[offset + 2] & 0xff) << 40) // BUG HERE > | ((buf[offset + 3] & 0xff) << 32) // BUG HERE > | ((buf[offset + 4] & 0xff) << 24) > | ((buf[offset + 5] & 0xff) << 16) > | ((buf[offset + 6] & 0xff) << 8) > | ((buf[offset + 7] & 0xff); > } > > This PR adds a new warning when the compiler detects an out-of-range bit shift, i.e., an `int` bit shift not in the range `[0...31]` or a `long` bit shift not in the range `[0...63]`. I think overall seems sensible - some questions/nits inline. make/jdk/src/classes/build/tools/intpoly/FieldGen.java line 631: > 629: + (params.getBitsPerLimb() - 1) + ";"); > 630: if (params.getBitsPerLimb() * params.getNumLimbs() != params.getPower()) { > 631: result.appendLine("@SuppressWarnings(\"lossy-conversions\")"); Do you know what is the specific problematic code generated here? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java line 4055: > 4053: int maximumShift; > 4054: switch (((OperatorSymbol)operator).opcode) { > 4055: case ByteCodes.ishl: Nit: use "modernized" switch - multiple case labels and `->`? test/langtools/tools/javac/lint/ShiftOutOfRange.java line 14: > 12: > 13: // These should generate warnings > 14: a = a << (byte)-1; Looking at the patch, I am not completely convinced disallowing `-1` is beneficial. On one hand, it looks weird. On the other hand, it makes some sense (as far as I can tell, it is universal for both `int` and `long`). And, unlike `128`, it is not clearly wrong. I am not sure if it wouldn't be better to simply permit `-1` as a special case. I see there are `<< -5` in the microbenchmark tests, but I think I am less inclined to accommodate negative values other than `-1`, as the semantics of those is much more cryptic, for me at least. Please let me know what you think. ------------- PR Review: https://git.openjdk.org/jdk/pull/27102#pullrequestreview-3411950069 PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487162366 PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487161036 PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487176078 From pavel.rappo at gmail.com Mon Nov 3 17:41:11 2025 From: pavel.rappo at gmail.com (Pavel Rappo) Date: Mon, 3 Nov 2025 17:41:11 +0000 Subject: Print suppressed exceptions in JShell In-Reply-To: References: Message-ID: >From the user?s perspective, it would be helpful to see suppressed exceptions. Even though it?s unusual to use try-with-resources (TWR) in hand-written JShell snippets, some methods _programmatically_ add suppressed exceptions to the exception they throw, so TWR isn?t required to see them. On Thu, Oct 30, 2025 at 11:41?PM Chen Liang wrote: > > On a second look, this is a bit more complex - the exception has to be transported. So UserException does not handle suppressed exceptions at all; ExecutionControlForwarder, LocalExecutionControl, StreamingExecutionControl all need to update for suppressed exception handling. In particular, changing the forwarder's protocol might be a bit risky; I wonder if we want to dig into this. > ________________________________ > From: compiler-dev on behalf of Chen Liang > Sent: Thursday, October 30, 2025 6:35 PM > To: Pavel Rappo ; compiler-dev at openjdk.org > Subject: Re: Print suppressed exceptions in JShell > > I think it is probably just an oversight. This seems to be printed by JShellTool::displayEvalException, which shouldn't be too hard to add printing for suppressed exceptions. > > -Chen > > > Confidential ? Oracle Internal > ________________________________ > From: compiler-dev on behalf of Pavel Rappo > Sent: Thursday, October 30, 2025 5:06 PM > To: compiler-dev at openjdk.org > Subject: Print suppressed exceptions in JShell > > Is there any reason why JShell does not print out suppressed > exceptions? I think it would be good to print them. > > jshell> new Throwable() > $1 ==> java.lang.Throwable > > jshell> new Error() > $2 ==> java.lang.Error > > jshell> $1.addSuppressed($2) > > jshell> throw $1 > | Exception java.lang.Throwable > | at (#1:1) > > -Pavel From rgiulietti at openjdk.org Mon Nov 3 18:12:13 2025 From: rgiulietti at openjdk.org (Raffaello Giulietti) Date: Mon, 3 Nov 2025 18:12:13 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain In-Reply-To: References: Message-ID: On Mon, 3 Nov 2025 16:47:56 GMT, Jan Lahoda wrote: >> When bit shifting an `int` or `long` value by an amount `X`, all but the last 5 or 6 (respectively) bits of `X` are ignored. >> >> This can create a trap for the unwary, as in this example: >> >> public long readLongBigEndian(byte[] buf, int offset) { >> return ((buf[offset + 0] & 0xff) << 56) // BUG HERE >> | ((buf[offset + 1] & 0xff) << 48) // BUG HERE >> | ((buf[offset + 2] & 0xff) << 40) // BUG HERE >> | ((buf[offset + 3] & 0xff) << 32) // BUG HERE >> | ((buf[offset + 4] & 0xff) << 24) >> | ((buf[offset + 5] & 0xff) << 16) >> | ((buf[offset + 6] & 0xff) << 8) >> | ((buf[offset + 7] & 0xff); >> } >> >> This PR adds a new warning when the compiler detects an out-of-range bit shift, i.e., an `int` bit shift not in the range `[0...31]` or a `long` bit shift not in the range `[0...63]`. > > test/langtools/tools/javac/lint/ShiftOutOfRange.java line 14: > >> 12: >> 13: // These should generate warnings >> 14: a = a << (byte)-1; > > Looking at the patch, I am not completely convinced disallowing `-1` is beneficial. On one hand, it looks weird. On the other hand, it makes some sense (as far as I can tell, it is universal for both `int` and `long`). And, unlike `128`, it is not clearly wrong. I am not sure if it wouldn't be better to simply permit `-1` as a special case. > > I see there are `<< -5` in the microbenchmark tests, but I think I am less inclined to accommodate negative values other than `-1`, as the semantics of those is much more cryptic, for me at least. > > Please let me know what you think. One way to read `v << -n` is: "Shift out everything to the left, except for the `n` least significant bits". Analogously for `v >>> -n`: "Shift out everything to the right, except for the `n` most significant bits". To rotate `v` by `n` bits to the left, for example, one can write `v << n | v >>> -n` (regardless of the width of `v`) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487416183 From vromero at openjdk.org Mon Nov 3 18:28:43 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 3 Nov 2025 18:28:43 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy [v3] In-Reply-To: References: Message-ID: > javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: > > - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType > - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop > > The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. > > This new visitor will compare types looking for exactness which is something desirable in a map key. > > TIA Vicente Romero has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains four additional commits since the last revision: - addressing review comments - Merge branch 'master' into JDK-8337142 - addressing review comments - 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28101/files - new: https://git.openjdk.org/jdk/pull/28101/files/ef427b38..da012a78 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28101&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28101&range=01-02 Stats: 7938 lines in 155 files changed: 4711 ins; 1856 del; 1371 mod Patch: https://git.openjdk.org/jdk/pull/28101.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28101/head:pull/28101 PR: https://git.openjdk.org/jdk/pull/28101 From vromero at openjdk.org Mon Nov 3 18:28:45 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 3 Nov 2025 18:28:45 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy [v2] In-Reply-To: References: <3vyz4FHRvN1mJZm5wCNEtPYdczimn-ghxuoK3YxlT64=.ffa6608e-a725-4210-94d8-c6cd5693cdb2@github.com> Message-ID: On Mon, 3 Nov 2025 16:02:43 GMT, Maurizio Cimadamore wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 3901: >> >>> 3899: boolean sameTypeArguments(List ts, List ss) { >>> 3900: while (ts.nonEmpty() && ss.nonEmpty() >>> 3901: && exactTypeVisitor.visit(ts.head, ss.head)) { >> >> You could delegate to `sameTypeComparator` here? > > Another possibility would be to declare an overloaded method to `isSameType` that takes a type argument comparator function. And maybe the default type argument comparator function is `containsTypeEquivalent` but then other clients could override that. I went for the first option. There is a public version of `containsTypeEquivalent` that takes two lists as arguments. For the second variant I think we would need to add the lambda to that method. We can add another version of that method but I think the first option is cleaner ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28101#discussion_r2487453067 From vromero at openjdk.org Mon Nov 3 18:35:02 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 3 Nov 2025 18:35:02 GMT Subject: Integrated: 8369654: javac OutOfMemoryError for complex intersection type In-Reply-To: References: Message-ID: On Wed, 29 Oct 2025 22:16:25 GMT, Vicente Romero wrote: > Javac is throwing an OOME for the code like: > > class Test { > interface WithMixin01 {} > // ... > // 20 interfaces here > interface WithMixin20 {} > > interface ClientA extends > WithMixin02, > WithMixin01, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > interface ClientB extends > WithMixin01, > WithMixin02, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > public static void main(String... args) { > ClientA a = null; > ClientB b = null; > String selector = "a"; > Object o = switch (selector) { > case "a" -> a; > case "b" -> b; > default -> null; > }; > } > } > > the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very slooooow. > > TIA This pull request has now been integrated. Changeset: 9f972008 Author: Vicente Romero URL: https://git.openjdk.org/jdk/commit/9f972008ff2beb4b69855f4c42b8a664a6b8bc95 Stats: 161 lines in 3 files changed: 147 ins; 2 del; 12 mod 8369654: javac OutOfMemoryError for complex intersection type Reviewed-by: liach, mcimadamore ------------- PR: https://git.openjdk.org/jdk/pull/28050 From vromero at openjdk.org Mon Nov 3 18:35:01 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 3 Nov 2025 18:35:01 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v12] In-Reply-To: References: Message-ID: On Mon, 3 Nov 2025 10:04:33 GMT, Maurizio Cimadamore wrote: > Very good -- thanks! thanks for the suggestions! ------------- PR Comment: https://git.openjdk.org/jdk/pull/28050#issuecomment-3481938493 From acobbs at openjdk.org Mon Nov 3 18:36:33 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 3 Nov 2025 18:36:33 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v2] In-Reply-To: References: Message-ID: > When bit shifting an `int` or `long` value by an amount `X`, all but the last 5 or 6 (respectively) bits of `X` are ignored. > > This can create a trap for the unwary, as in this example: > > public long readLongBigEndian(byte[] buf, int offset) { > return ((buf[offset + 0] & 0xff) << 56) // BUG HERE > | ((buf[offset + 1] & 0xff) << 48) // BUG HERE > | ((buf[offset + 2] & 0xff) << 40) // BUG HERE > | ((buf[offset + 3] & 0xff) << 32) // BUG HERE > | ((buf[offset + 4] & 0xff) << 24) > | ((buf[offset + 5] & 0xff) << 16) > | ((buf[offset + 6] & 0xff) << 8) > | ((buf[offset + 7] & 0xff); > } > > This PR adds a new warning when the compiler detects an out-of-range bit shift, i.e., an `int` bit shift not in the range `[0...31]` or a `long` bit shift not in the range `[0...63]`. Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 10 commits: - Merge branch 'master' into JDK-5038439 to fix conflict. - Address review comment (combine switch cases). - Merge branch 'master' into JDK-5038439 to fix conflict. - Add "long" as a supported message parameter type. - Use "bit(s)" instead of "bits" where value could be 1. - Merge branch 'master' into JDK-5038439 - Sprinkle more variety into the regression test. - Minor diff cleanup. - Update "lossy-conversions" description in compiler module Javadoc. - Warn for bit shifts using an out-of-range shift amount. ------------- Changes: https://git.openjdk.org/jdk/pull/27102/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27102&range=01 Stats: 181 lines in 13 files changed: 173 ins; 0 del; 8 mod Patch: https://git.openjdk.org/jdk/pull/27102.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27102/head:pull/27102 PR: https://git.openjdk.org/jdk/pull/27102 From acobbs at openjdk.org Mon Nov 3 18:36:35 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 3 Nov 2025 18:36:35 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v2] In-Reply-To: References: Message-ID: <0D_jgs9w47rAKwt5Udla_7C1bfb7Moc14-Fr4RsTq64=.27341088-069f-4208-817e-7391e1348a54@github.com> On Mon, 3 Nov 2025 16:44:13 GMT, Jan Lahoda wrote: >> Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 10 commits: >> >> - Merge branch 'master' into JDK-5038439 to fix conflict. >> - Address review comment (combine switch cases). >> - Merge branch 'master' into JDK-5038439 to fix conflict. >> - Add "long" as a supported message parameter type. >> - Use "bit(s)" instead of "bits" where value could be 1. >> - Merge branch 'master' into JDK-5038439 >> - Sprinkle more variety into the regression test. >> - Minor diff cleanup. >> - Update "lossy-conversions" description in compiler module Javadoc. >> - Warn for bit shifts using an out-of-range shift amount. > > make/jdk/src/classes/build/tools/intpoly/FieldGen.java line 631: > >> 629: + (params.getBitsPerLimb() - 1) + ";"); >> 630: if (params.getBitsPerLimb() * params.getNumLimbs() != params.getPower()) { >> 631: result.appendLine("@SuppressWarnings(\"lossy-conversions\")"); > > Do you know what is the specific problematic code generated here? Actually this goes away after merging int the latest master. It was fixed independently by JDK-8368301. > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java line 4055: > >> 4053: int maximumShift; >> 4054: switch (((OperatorSymbol)operator).opcode) { >> 4055: case ByteCodes.ishl: > > Nit: use "modernized" switch - multiple case labels and `->`? We can combined the labels, but since we're setting _two_ values we can't use the `->` syntax. Fixed in 8044632727d. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487476213 PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487476095 From acobbs at openjdk.org Mon Nov 3 18:36:37 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 3 Nov 2025 18:36:37 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v2] In-Reply-To: References: Message-ID: On Mon, 3 Nov 2025 18:09:01 GMT, Raffaello Giulietti wrote: >> test/langtools/tools/javac/lint/ShiftOutOfRange.java line 14: >> >>> 12: >>> 13: // These should generate warnings >>> 14: a = a << (byte)-1; >> >> Looking at the patch, I am not completely convinced disallowing `-1` is beneficial. On one hand, it looks weird. On the other hand, it makes some sense (as far as I can tell, it is universal for both `int` and `long`). And, unlike `128`, it is not clearly wrong. I am not sure if it wouldn't be better to simply permit `-1` as a special case. >> >> I see there are `<< -5` in the microbenchmark tests, but I think I am less inclined to accommodate negative values other than `-1`, as the semantics of those is much more cryptic, for me at least. >> >> Please let me know what you think. > > One way to read `v << -n` is: "Shift out everything to the left, except for the `n` least significant bits". > Analogously for `v >>> -n`: "Shift out everything to the right, except for the `n` most significant bits". > > To rotate `v` by `n` bits to the left, for example, one can write `v << n | v >>> -n` (regardless of the width of `v`) Hmm, obviously this is a judgement call and I'm curious what others think. My opinion is that I still think there should be a warning for shifts of -1. I mean, maybe to a _real_ hacker, then of course `foo << -1` makes perfect sense because it's just stating the "obvious" which is "shift the low order bit into the high order position and set all the other bits to zero", right?? :) I just don't think the average Java programmer automatically understands that. Yes, it's an idiom or "handy trick", but if hasn't attained the status of being universally recognized then it doesn't deserve a special exception. On the other hand, excluding -1 from the warning would be less disruptive (at least, to the real hackers out there), and that has its own merits. So I don't have a super strong opinion about it. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487476314 From hgreule at openjdk.org Mon Nov 3 18:36:39 2025 From: hgreule at openjdk.org (Hannes Greule) Date: Mon, 3 Nov 2025 18:36:39 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v2] In-Reply-To: References: Message-ID: <05yTbGH4d3Remac9l0EN0P6Li94CmDTyXvalkwb5vhI=.1a640f2e-df85-4add-88a9-e6613cfe3f4c@github.com> On Mon, 3 Nov 2025 18:32:57 GMT, Archie Cobbs wrote: >> When bit shifting an `int` or `long` value by an amount `X`, all but the last 5 or 6 (respectively) bits of `X` are ignored. >> >> This can create a trap for the unwary, as in this example: >> >> public long readLongBigEndian(byte[] buf, int offset) { >> return ((buf[offset + 0] & 0xff) << 56) // BUG HERE >> | ((buf[offset + 1] & 0xff) << 48) // BUG HERE >> | ((buf[offset + 2] & 0xff) << 40) // BUG HERE >> | ((buf[offset + 3] & 0xff) << 32) // BUG HERE >> | ((buf[offset + 4] & 0xff) << 24) >> | ((buf[offset + 5] & 0xff) << 16) >> | ((buf[offset + 6] & 0xff) << 8) >> | ((buf[offset + 7] & 0xff); >> } >> >> This PR adds a new warning when the compiler detects an out-of-range bit shift, i.e., an `int` bit shift not in the range `[0...31]` or a `long` bit shift not in the range `[0...63]`. > > Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 10 commits: > > - Merge branch 'master' into JDK-5038439 to fix conflict. > - Address review comment (combine switch cases). > - Merge branch 'master' into JDK-5038439 to fix conflict. > - Add "long" as a supported message parameter type. > - Use "bit(s)" instead of "bits" where value could be 1. > - Merge branch 'master' into JDK-5038439 > - Sprinkle more variety into the regression test. > - Minor diff cleanup. > - Update "lossy-conversions" description in compiler module Javadoc. > - Warn for bit shifts using an out-of-range shift amount. test/langtools/tools/javac/lint/ShiftOutOfRange.java line 18: > 16: a = a >>> (short)-1; > 17: a <<= -1; > 18: a >>= -1L; // also generates "implicit cast from long to int in compound assignment is possibly lossy" I'm a bit surprised by the additional warning here. The shift still operates on int, not long; i.e., unary promotion is performed for each argument rather than binary promotion https://docs.oracle.com/javase/specs/jls/se25/html/jls-15.html#jls-15.19 Should this be fixed (separately, obviously)? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487472103 From acobbs at openjdk.org Mon Nov 3 18:56:27 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 3 Nov 2025 18:56:27 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v2] In-Reply-To: <05yTbGH4d3Remac9l0EN0P6Li94CmDTyXvalkwb5vhI=.1a640f2e-df85-4add-88a9-e6613cfe3f4c@github.com> References: <05yTbGH4d3Remac9l0EN0P6Li94CmDTyXvalkwb5vhI=.1a640f2e-df85-4add-88a9-e6613cfe3f4c@github.com> Message-ID: On Mon, 3 Nov 2025 18:30:22 GMT, Hannes Greule wrote: >> Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 10 commits: >> >> - Merge branch 'master' into JDK-5038439 to fix conflict. >> - Address review comment (combine switch cases). >> - Merge branch 'master' into JDK-5038439 to fix conflict. >> - Add "long" as a supported message parameter type. >> - Use "bit(s)" instead of "bits" where value could be 1. >> - Merge branch 'master' into JDK-5038439 >> - Sprinkle more variety into the regression test. >> - Minor diff cleanup. >> - Update "lossy-conversions" description in compiler module Javadoc. >> - Warn for bit shifts using an out-of-range shift amount. > > test/langtools/tools/javac/lint/ShiftOutOfRange.java line 18: > >> 16: a = a >>> (short)-1; >> 17: a <<= -1; >> 18: a >>= -1L; // also generates "implicit cast from long to int in compound assignment is possibly lossy" > > I'm a bit surprised by the additional warning here. The shift still operates on int, not long; i.e., unary promotion is performed for each argument rather than binary promotion https://docs.oracle.com/javase/specs/jls/se25/html/jls-15.html#jls-15.19 > > Should this be fixed (separately, obviously)? I agree, this is a separate compiler glitch. I've created [JDK-8371162](https://bugs.openjdk.org/browse/JDK-8371162). ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487531814 From rriggs at openjdk.org Mon Nov 3 19:15:13 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Mon, 3 Nov 2025 19:15:13 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v2] In-Reply-To: References: Message-ID: On Mon, 3 Nov 2025 18:31:54 GMT, Archie Cobbs wrote: >> One way to read `v << -n` is: "Shift out everything to the left, except for the `n` least significant bits". >> Analogously for `v >>> -n`: "Shift out everything to the right, except for the `n` most significant bits". >> >> To rotate `v` by `n` bits to the left, for example, one can write `v << n | v >>> -n` (regardless of the width of `v`) > > Hmm, obviously this is a judgement call and I'm curious what others think. > > My opinion is that I still think there should be a warning for shifts of -1. > > I mean, maybe to a _real_ hacker, then of course `foo << -1` makes perfect sense because it's just stating the "obvious" which is "shift the low order bit into the high order position and set all the other bits to zero", right?? :) > > I just don't think the average Java programmer automatically understands that. > > Yes, it's an idiom or "handy trick", but if hasn't attained the status of being universally recognized then it doesn't deserve a special exception. > > On the other hand, excluding -1 from the warning would be less disruptive (at least, to the real hackers out there), and that has its own merits. So I don't have a super strong opinion about it. This might be worth a corpus scan to see how common it is to shift by -1 or other constants, either int or long. Someone, might interpret `v << -1` as a right shift, is it more likely to misinterpret it as using more than 5/6 bits of the shift or considering it signed. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487576716 From vyazici at openjdk.org Tue Nov 4 09:00:17 2025 From: vyazici at openjdk.org (Volkan Yazici) Date: Tue, 4 Nov 2025 09:00:17 GMT Subject: RFR: 8371133: Clarify the purpose of "src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties" Message-ID: Document usage and purpose of `ct.properties`. ------------- Commit messages: - Document `ct.properties` Changes: https://git.openjdk.org/jdk/pull/28123/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28123&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8371133 Stats: 9 lines in 1 file changed: 8 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/28123.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28123/head:pull/28123 PR: https://git.openjdk.org/jdk/pull/28123 From jlahoda at openjdk.org Tue Nov 4 10:21:28 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 4 Nov 2025 10:21:28 GMT Subject: RFR: 8371133: Clarify the purpose of "src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties" In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 08:46:50 GMT, Volkan Yazici wrote: > Document usage and purpose of `ct.properties`. src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties line 26: > 24: # > 25: > 26: # This file is used by `com.sun.tools.javac.file.JRTIndex` to generate How about phrasing like this (`JRTIndex` uses the data defined here, but does not generate the `.java` file - parts of the build system do): # This file was originally used to produce the `proprietary` warning when # accessing non-APIs, and to hide some non-APIs in JDK <= 8. This has been # superseded by the module system and `--release`. But, when compiling with # `--source 8`, it is still used for this purpose by `com.sun.tools.javac.file.JRTIndex`. # # The build generates `jdk.compiler/com/sun/tools/javac/resources/ct.java` from # this file, which is then used at runtime. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28123#discussion_r2489747244 From jpai at openjdk.org Tue Nov 4 10:42:29 2025 From: jpai at openjdk.org (Jaikiran Pai) Date: Tue, 4 Nov 2025 10:42:29 GMT Subject: RFR: 8365699: Remove jdk.internal.javac.PreviewFeature.Feature enum values for features finalized in Java 25 or earlier Message-ID: Can I please get a review of this change which cleans up the outdated enum constants in the internal `jdk.internal.javac.PreviewFeature$Feature` enum? This addresses https://bugs.openjdk.org/browse/JDK-8365699. As noted in that issue, this enum has accumulated some outdated preview feature constants which are no longer needed. The changes in this PR removes those enum constants whose preview features have been finalized in Java 25 or earlier (the current mainline bootstrap JDK is Java 25). A code comment explaining the lifetime of these enum constants has also been added. No new tests have been introduced and tier1, tier2, tier3 testing is currently in progress in the CI. ------------- Commit messages: - 8365699: Remove jdk.internal.javac.PreviewFeature.Feature enum values for features finalized in Java 25 or earlier Changes: https://git.openjdk.org/jdk/pull/28128/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28128&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8365699 Stats: 23 lines in 1 file changed: 15 ins; 6 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/28128.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28128/head:pull/28128 PR: https://git.openjdk.org/jdk/pull/28128 From jlahoda at openjdk.org Tue Nov 4 10:59:11 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 4 Nov 2025 10:59:11 GMT Subject: RFR: 8155591: Misleading warning when not overriding close method in interface extending AutoCloseable [v2] In-Reply-To: References: Message-ID: On Tue, 23 Sep 2025 17:19:23 GMT, Archie Cobbs wrote: >> The compiler generates a warning if you declare a `close()` method that throws any supertype of `InterruptedException` in a class or interface extending `AutoCloseable`. This is because suppressed `InterruptedException`'s are likely to lead to misbehavior at runtime. >> >> However, this feature also generates a warning due to `AutoCloseable.close()` itself, if you simply inherit it. For example: >> >> $ cat MyClass.java >> public interface MyClass extends AutoCloseable { >> } >> $ javac -Xlint:try MyClass.java >> MyClass.java:1: warning: [try] auto-closeable resource MyClass has a member method close() that could throw InterruptedException >> public interface MyClass extends AutoCloseable { >> ^ >> 1 warning >> >> The warning is not useful because `AutoCloseable.close()` is abstract and so it's going to be some other class' job to deal with the throws clause. >> >> This change prevents `AutoCloseable.close()` itself from triggering the warning in a class declaration. We preserve the existing behavior in which a warning is generated at the use site (i.e., at the try-with-resources statement). > > Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains two additional commits since the last revision: > > - Merge branch 'master' into JDK-8155591 to get recent build fixes. > - Don't warn about AutoCloseable.close() itself throwing InterruptedException. Makes sense to me. I think it would be useful if the tests would be enhanced to cover the case where the `close` method declaration in non-AutoClo does actually `Exception`/`InterruptedException`. I found `InterruptedExceptionTest.java`, but as that's a combo test, it is harder to see a sensible warning is produced on a sensible place. Regarding sensible place, it would be possible to produce a warning specifically at the problematic `close` method (if it is declared in the given class, and not inherited) using `TreeInfo.diagnosticPositionFor`, but it is not so easy in this case - among other things, the warning would probably need a different wording. Up to you. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27062#issuecomment-3485318048 From vyazici at openjdk.org Tue Nov 4 12:18:34 2025 From: vyazici at openjdk.org (Volkan Yazici) Date: Tue, 4 Nov 2025 12:18:34 GMT Subject: RFR: 8371133: Clarify the purpose of "src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties" [v2] In-Reply-To: References: Message-ID: > Document usage and purpose of `ct.properties`. Volkan Yazici has updated the pull request incrementally with one additional commit since the last revision: Apply review feedback ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28123/files - new: https://git.openjdk.org/jdk/pull/28123/files/9edb525a..476a98d3 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28123&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28123&range=00-01 Stats: 8 lines in 1 file changed: 4 ins; 3 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/28123.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28123/head:pull/28123 PR: https://git.openjdk.org/jdk/pull/28123 From vyazici at openjdk.org Tue Nov 4 12:18:36 2025 From: vyazici at openjdk.org (Volkan Yazici) Date: Tue, 4 Nov 2025 12:18:36 GMT Subject: RFR: 8371133: Clarify the purpose of "src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties" [v2] In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 10:18:57 GMT, Jan Lahoda wrote: >> Volkan Yazici has updated the pull request incrementally with one additional commit since the last revision: >> >> Apply review feedback > > src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties line 26: > >> 24: # >> 25: >> 26: # This file is used by `com.sun.tools.javac.file.JRTIndex` to generate > > How about phrasing like this (`JRTIndex` uses the data defined here, but does not generate the `.java` file - parts of the build system do): > > # This file was originally used to produce the `proprietary` warning when > # accessing non-APIs, and to hide some non-APIs in JDK <= 8. This has been > # superseded by the module system and `--release`. But, when compiling with > # `--source 8`, it is still used for this purpose by `com.sun.tools.javac.file.JRTIndex`. > # > # The build generates `jdk.compiler/com/sun/tools/javac/resources/ct.java` from > # this file, which is then used at runtime. Applied in 476a98d3460. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28123#discussion_r2490274420 From nbenalla at openjdk.org Tue Nov 4 12:27:43 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Tue, 4 Nov 2025 12:27:43 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 Message-ID: Get JDK 27 underway. ------------- Commit messages: - initial commit start-of-JDK-27 Changes: https://git.openjdk.org/jdk/pull/28130/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8370890 Stats: 90 lines in 34 files changed: 46 ins; 0 del; 44 mod Patch: https://git.openjdk.org/jdk/pull/28130.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28130/head:pull/28130 PR: https://git.openjdk.org/jdk/pull/28130 From nbenalla at openjdk.org Tue Nov 4 12:27:43 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Tue, 4 Nov 2025 12:27:43 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 11:45:04 GMT, Nizar Benalla wrote: > Get JDK 27 underway. This initial version of the PR intentionally excludes the creation of the new symbol files so that the fundamental code aspects of the update are easier to see. The GA release date is accurate. The URL of the JVMLS will be updated in the next commit to be accurate. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28130#issuecomment-3485695380 From jlahoda at openjdk.org Tue Nov 4 14:53:32 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 4 Nov 2025 14:53:32 GMT Subject: RFR: 8369489: Marker annotation on inner class access crashes javac compiler [v2] In-Reply-To: References: Message-ID: <2MDD-eawPdZWHZl3tJ0JMbovqlYuiC7weyGrPtfrZzM=.2a87e1c1-6eb6-4e8d-b853-b415d3c03e63@github.com> > Consider code like: > > I i = @Ann Object[]::new; > > > the initializer is a method reference over an array type, whose component is annotated - that follows from the grammar in JLS 4.3, and also matches what is parsed for code like: > > I i = (@Ann Object[]) null; > > > But, the javac's parser will create a method reference, whose type is an annotated type - which is wrong. And also fails if the array type as such is also annotated. > > The proposal herein is to simply use `insertAnnotationsToMostInner` to put the annotation at the correct place, as is done on other similar places. This one attaches the annotation at the correct nesting level. > > Sadly, the code may be something very broken like: > > I i = @Ann foobar()::new; > > > and `insertAnnotationsToMostInner` would fail for this code/AST. Hence if the method reference is not over a type, we'll create an `AnnotatedType` (to keep the info in the AST as before) + an error + an error AST node. Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains four commits: - Merge branch 'master' into JDK-8369489 - Fixing error recovery. - Adjusting member ref position to sensible values. - 8369489: Marker annotation on inner class access crashes javac compiler ------------- Changes: https://git.openjdk.org/jdk/pull/27864/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27864&range=01 Stats: 249 lines in 4 files changed: 240 ins; 5 del; 4 mod Patch: https://git.openjdk.org/jdk/pull/27864.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27864/head:pull/27864 PR: https://git.openjdk.org/jdk/pull/27864 From abimpoudis at openjdk.org Tue Nov 4 16:12:46 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Tue, 4 Nov 2025 16:12:46 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v4] In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 14:11:54 GMT, Aggelos Biboudis wrote: >> Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 23 commits: >> >> - Merge branch 'JDK-8364991' into JDK-8367530 >> - Fixing tests >> - Merge branch 'JDK-8364991-2' into JDK-8367530-2 >> - Better visualisation. >> - Merge branch 'JDK-8367499' into JDK-8367530 >> - Merge branch 'JDK-8364991' into JDK-8367499 >> - Fixing tests. >> - Cleanup. >> - Cleanup. >> - Cleanup. >> - ... and 13 more: https://git.openjdk.org/jdk/compare/e6a3f0da...b7c33349 > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 948: > >> 946: //combine sealed subtypes into the supertype, if all is covered. >> 947: //but preserve more specific record types in positions where there are record patterns in the original patterns >> 948: //this is particularly for the case where the sealed supertype only has one permitted type, the record > > There is a word missing:"this is particularly *important* for" I think, right? Interesting. This is a property for NR-1S that shows up here too. Nice. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2490694687 From abimpoudis at openjdk.org Tue Nov 4 16:12:44 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Tue, 4 Nov 2025 16:12:44 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v4] In-Reply-To: References: Message-ID: On Mon, 3 Nov 2025 15:10:49 GMT, Jan Lahoda wrote: >> Consider code like: >> >> package test; >> public class Test { >> private int test(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> ``` >> >> This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> The goal of this PR is to improve the error, at least in some cases to something along these lines: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> missing patterns: >> test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) >> 1 error >> >> >> The (very simplified) way it works in a recursive (or induction) way: >> - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. >> - for a current missing pattern, try to enhance it: >> - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. >> - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. >> >> This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. >> >> There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. >> >> Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. >> >> There's also an open possibility for select tools to... > > Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 23 commits: > > - Merge branch 'JDK-8364991' into JDK-8367530 > - Fixing tests > - Merge branch 'JDK-8364991-2' into JDK-8367530-2 > - Better visualisation. > - Merge branch 'JDK-8367499' into JDK-8367530 > - Merge branch 'JDK-8364991' into JDK-8367499 > - Fixing tests. > - Cleanup. > - Cleanup. > - Cleanup. > - ... and 13 more: https://git.openjdk.org/jdk/compare/e6a3f0da...b7c33349 This is a MEGA PR. Many congratulations @lahodaj. ? This is a first pass. I will come back to it again as I am slowly progressing into understanding it better. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 157: > 155: .stream() > 156: .flatMap(pd -> { > 157: if (pd instanceof BindingPattern bp && enum2Constants.containsKey(bp.type.tsym)) { Can this be subsumed into `computeMissingPatternDescriptions` just to handle the generation of all kinds of incomplete patterns inside there? It seems to be that this client-side would be clearer, but ignore if it would be too much fuss. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 173: > 171: } > 172: > 173: private CoverageResult computeCoverage(Type selectorType, Set patterns, boolean search) { This extra boolean parameter is subtle (because previously we didn't have a new mode of execution). Can you introduce either a top-level comment at the `computeCoverage` method or something more descriptive than `search` or an enumeration with the two modes? Because now it is calculating both the coverage result and the inverse (uncovered patterns). src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 351: > 349: Type instantiated = instantiatePatternType(targetType, csym); > 350: > 351: return instantiated != null && types.isCastable(targetType, instantiated); If inference fails, does this mean that we get an exhaustiveness error with a sample generic instantiation? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 836: > 834: if (toExpand instanceof BindingPattern bp) { > 835: if (bp.type.tsym.isSealed()) { > 836: //try to replace binding patterns for sealed types with all their immediate permitted types: Can you reuse the word "viablePermittedPatterns" in this comment? That way the reader can formulate the properties of what this variable represents, faster. IIUC this is a process of minimization going from the `viablePermittedPatterns` to `reducedPermittedPatterns`. Not only that, but (I think) there is a property that reduction means that you prune the combinatorial space as long as there are no variables *and* the pattern is the most general. The actual invariants are actually coming from `isPossibleSubtypePredicate` which ensures castability and pattern inference. I wonder how can we end up here with completely incompatible classes? (final A, final B) (so that the castability check return false in `isPossibleSubtypePredicate`). Wouldn't that be an error of applicability? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 893: > 891: > 892: for (Type componentType : componentTypes) { > 893: List variants; Is this the same conceptually to `viablePermittedPatterns` for the binding patterns case? If yes, we can reuse the same name (just to match the concepts)? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 924: > 922: .collect(Collectors.toCollection(HashSet::new)); > 923: > 924: //remove unnecessary: It seems that the removal of the unnecessary patterns is common to the next step as well? If yes, would it be beneficial to extract? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 948: > 946: //combine sealed subtypes into the supertype, if all is covered. > 947: //but preserve more specific record types in positions where there are record patterns in the original patterns > 948: //this is particularly for the case where the sealed supertype only has one permitted type, the record There is a word missing:"this is particularly *important* for" I think, right? ------------- PR Review: https://git.openjdk.org/jdk/pull/27256#pullrequestreview-3416390483 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2490487291 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2490461430 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2491048541 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2490585550 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2490667198 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2490594825 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2490682402 From mcimadamore at openjdk.org Tue Nov 4 16:38:29 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Tue, 4 Nov 2025 16:38:29 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy [v3] In-Reply-To: References: Message-ID: <97nAwH2eW-S0h6YmGalbzJCRLioJIKPEI190360QK-w=.b0e1e371-abdd-45fc-82fd-92ae2f460490@github.com> On Mon, 3 Nov 2025 18:28:43 GMT, Vicente Romero wrote: >> javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: >> >> - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType >> - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop >> >> The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. >> >> This new visitor will compare types looking for exactness which is something desirable in a map key. >> >> TIA > > Vicente Romero has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains four additional commits since the last revision: > > - addressing review comments > - Merge branch 'master' into JDK-8337142 > - addressing review comments > - 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy Looks good, thanks. I hope the performance of the type comparison doesn't regress too much (given that there's more virtual calls in the middle). ------------- Marked as reviewed by mcimadamore (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28101#pullrequestreview-3417490888 From cstein at openjdk.org Tue Nov 4 16:49:31 2025 From: cstein at openjdk.org (Christian Stein) Date: Tue, 4 Nov 2025 16:49:31 GMT Subject: RFR: 8278856: javac documentation does not mention use of Manifest class-path attribute [v2] In-Reply-To: References: Message-ID: > Please review this improvement to `javac`'s manpage, section **Directory Hierarchies**. Christian Stein has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains two additional commits since the last revision: - Merge branch 'openjdk:master' into patch-2 - 8278856: javac documentation does not mention use of Manifest class-path attribute ------------- Changes: - all: https://git.openjdk.org/jdk/pull/22243/files - new: https://git.openjdk.org/jdk/pull/22243/files/5799d8a9..ec71757e Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=22243&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=22243&range=00-01 Stats: 1445838 lines in 19140 files changed: 785063 ins; 536765 del; 124010 mod Patch: https://git.openjdk.org/jdk/pull/22243.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/22243/head:pull/22243 PR: https://git.openjdk.org/jdk/pull/22243 From vromero at openjdk.org Tue Nov 4 16:50:32 2025 From: vromero at openjdk.org (Vicente Romero) Date: Tue, 4 Nov 2025 16:50:32 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy In-Reply-To: References: Message-ID: On Mon, 3 Nov 2025 13:04:53 GMT, Maurizio Cimadamore wrote: >> javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: >> >> - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType >> - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop >> >> The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. >> >> This new visitor will compare types looking for exactness which is something desirable in a map key. >> >> TIA > > I did some more analysis. It seems like inference completes correctly. But at the last step we end up with a very complex type (for the type variable in List::of): > > > M&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>,? extends java.lang.Object&Nine&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Six&Thirteen&Eleven&Thirteen&Eleven&Thir teen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Six>> > > > (!!) > > In the very last step of inference we have to check if this is a subtype of Object (the upper bound of the tvar). And this crashes javac, because subtyping needs to capture and capture triggers a glb involving this huge type which then consumes the stack. > > Eventually this computation ends up in `containsTypeRecursive` with these two types: > > > T = Test.Ten&Test.Thirteen&Test.Eleven&Test.Thirteen>&Test.Thirteen>> > > S = Test.Ten&Test.Thirteen> > > > At which point we keep looping forever because, to check if we have already seen this type pair, we need to perform (as you said), a nested containment check which brings us back here. So, we never decide whether we can add the type pair to the cache or not... > > So, your fix seems to be correct -- we need a simpler way to structurally compares two types w/o calling back into containment. @mcimadamore thanks for the review! ------------- PR Comment: https://git.openjdk.org/jdk/pull/28101#issuecomment-3486976235 From vromero at openjdk.org Tue Nov 4 16:50:34 2025 From: vromero at openjdk.org (Vicente Romero) Date: Tue, 4 Nov 2025 16:50:34 GMT Subject: Integrated: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy In-Reply-To: References: Message-ID: On Sun, 2 Nov 2025 02:12:40 GMT, Vicente Romero wrote: > javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: > > - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType > - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop > > The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. > > This new visitor will compare types looking for exactness which is something desirable in a map key. > > TIA This pull request has now been integrated. Changeset: 4c6af03f Author: Vicente Romero URL: https://git.openjdk.org/jdk/commit/4c6af03f81e068a98b8f4628b96682a54f3946da Stats: 102 lines in 2 files changed: 96 ins; 0 del; 6 mod 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy Reviewed-by: mcimadamore ------------- PR: https://git.openjdk.org/jdk/pull/28101 From jlahoda at openjdk.org Tue Nov 4 17:03:43 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 4 Nov 2025 17:03:43 GMT Subject: RFR: 8278856: javac documentation does not mention use of Manifest class-path attribute [v2] In-Reply-To: References: Message-ID: On Tue, 19 Nov 2024 16:13:16 GMT, Christian Stein wrote: >> Christian Stein has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains two additional commits since the last revision: >> >> - Merge branch 'openjdk:master' into patch-2 >> - 8278856: javac documentation does not mention use of Manifest class-path attribute > > src/jdk.compiler/share/man/javac.md line 1291: > >> 1289: and the specified JAR file(s) exist, they are automatically inserted into the >> 1290: user class path after the JAR file. This rule also applies recursively to any >> 1291: new JAR files found. Consult the [JAR File Specification](../jar/jar.html#class-path-attribute) > > The link to the `jar.html` file using the relative path `../jar/` should lead to the JAR File Specification document. For JavaSE 23, that specification documentation is located at https://docs.oracle.com/en/java/javase/23/docs/specs/jar/jar.html > > How can I test that the online version, for 23 hosted at https://docs.oracle.com/en/java/javase/23/docs/specs/man/javac.html, contains the correct link target? I see javadoc uses a similar approach: https://github.com/openjdk/jdk/blob/4c6af03f81e068a98b8f4628b96682a54f3946da/src/jdk.javadoc/share/man/javadoc.md?plain=1#L101 So the link here is probably OK, but I don't know what is the way to check. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/22243#discussion_r2491325249 From vromero at openjdk.org Tue Nov 4 18:30:08 2025 From: vromero at openjdk.org (Vicente Romero) Date: Tue, 4 Nov 2025 18:30:08 GMT Subject: RFR: 8369489: Marker annotation on inner class access crashes javac compiler [v2] In-Reply-To: <2MDD-eawPdZWHZl3tJ0JMbovqlYuiC7weyGrPtfrZzM=.2a87e1c1-6eb6-4e8d-b853-b415d3c03e63@github.com> References: <2MDD-eawPdZWHZl3tJ0JMbovqlYuiC7weyGrPtfrZzM=.2a87e1c1-6eb6-4e8d-b853-b415d3c03e63@github.com> Message-ID: On Tue, 4 Nov 2025 14:53:32 GMT, Jan Lahoda wrote: >> Consider code like: >> >> I i = @Ann Object[]::new; >> >> >> the initializer is a method reference over an array type, whose component is annotated - that follows from the grammar in JLS 4.3, and also matches what is parsed for code like: >> >> I i = (@Ann Object[]) null; >> >> >> But, the javac's parser will create a method reference, whose type is an annotated type - which is wrong. And also fails if the array type as such is also annotated. >> >> The proposal herein is to simply use `insertAnnotationsToMostInner` to put the annotation at the correct place, as is done on other similar places. This one attaches the annotation at the correct nesting level. >> >> Sadly, the code may be something very broken like: >> >> I i = @Ann foobar()::new; >> >> >> and `insertAnnotationsToMostInner` would fail for this code/AST. Hence if the method reference is not over a type, we'll create an `AnnotatedType` (to keep the info in the AST as before) + an error + an error AST node. > > Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains four commits: > > - Merge branch 'master' into JDK-8369489 > - Fixing error recovery. > - Adjusting member ref position to sensible values. > - 8369489: Marker annotation on inner class access crashes javac compiler lgtm ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27864#pullrequestreview-3418109245 From darcy at openjdk.org Tue Nov 4 18:47:51 2025 From: darcy at openjdk.org (Joe Darcy) Date: Tue, 4 Nov 2025 18:47:51 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 In-Reply-To: References: Message-ID: <4YP2knvpGm61PssS9EtEX4W35vd90XLOjgkevNqaBF0=.e5a34d1c-4f3d-407e-b53d-789a97682a0d@github.com> On Tue, 4 Nov 2025 11:45:04 GMT, Nizar Benalla wrote: > Get JDK 27 underway. Looks fine so far. ------------- PR Review: https://git.openjdk.org/jdk/pull/28130#pullrequestreview-3418178547 From nbenalla at openjdk.org Tue Nov 4 20:11:23 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Tue, 4 Nov 2025 20:11:23 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 [v2] In-Reply-To: References: Message-ID: <3cZuldBvytdN_Hu0qlLhUkrCsH5EUlZJ5SEjnF8SLEU=.e76693bd-f6e1-4f8a-9dd5-699c9e4306bf@github.com> > Get JDK 27 underway. Nizar Benalla has updated the pull request incrementally with one additional commit since the last revision: add missing enum ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28130/files - new: https://git.openjdk.org/jdk/pull/28130/files/cc1a968e..647904b3 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=00-01 Stats: 1 line in 1 file changed: 1 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/28130.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28130/head:pull/28130 PR: https://git.openjdk.org/jdk/pull/28130 From nbenalla at openjdk.org Tue Nov 4 20:24:52 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Tue, 4 Nov 2025 20:24:52 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 [v3] In-Reply-To: References: Message-ID: > Get JDK 27 underway. Nizar Benalla has updated the pull request incrementally with one additional commit since the last revision: update links to JVMS 26 and 27 ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28130/files - new: https://git.openjdk.org/jdk/pull/28130/files/647904b3..b51f2324 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=01-02 Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/28130.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28130/head:pull/28130 PR: https://git.openjdk.org/jdk/pull/28130 From acobbs at openjdk.org Tue Nov 4 23:56:30 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Tue, 4 Nov 2025 23:56:30 GMT Subject: RFR: 8155591: Misleading warning when not overriding close method in interface extending AutoCloseable [v2] In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 10:56:24 GMT, Jan Lahoda wrote: >> Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains two additional commits since the last revision: >> >> - Merge branch 'master' into JDK-8155591 to get recent build fixes. >> - Don't warn about AutoCloseable.close() itself throwing InterruptedException. > > Makes sense to me. I think it would be useful if the tests would be enhanced to cover the case where the `close` method declaration in non-AutoClo does actually `Exception`/`InterruptedException`. I found `InterruptedExceptionTest.java`, but as that's a combo test, it is harder to see a sensible warning is produced on a sensible place. > > Regarding sensible place, it would be possible to produce a warning specifically at the problematic `close` method (if it is declared in the given class, and not inherited) using `TreeInfo.diagnosticPositionFor`, but it is not so easy in this case - among other things, the warning would probably need a different wording. Up to you. Hi @lahodaj thanks for taking a look. I just realized there is another potential issue. Shouldn't a warning also be generated in this example? class WithClose { public void close() throws Exception { } } public class Try extends WithClose implements AutoCloseable { } Currently the compiler does not generate one; I'm not sure yet what exact logical tweak would be needed. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27062#issuecomment-3488465787 From jlahoda at openjdk.org Wed Nov 5 05:47:16 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 5 Nov 2025 05:47:16 GMT Subject: Integrated: 8369489: Marker annotation on inner class access crashes javac compiler In-Reply-To: References: Message-ID: On Fri, 17 Oct 2025 11:49:15 GMT, Jan Lahoda wrote: > Consider code like: > > I i = @Ann Object[]::new; > > > the initializer is a method reference over an array type, whose component is annotated - that follows from the grammar in JLS 4.3, and also matches what is parsed for code like: > > I i = (@Ann Object[]) null; > > > But, the javac's parser will create a method reference, whose type is an annotated type - which is wrong. And also fails if the array type as such is also annotated. > > The proposal herein is to simply use `insertAnnotationsToMostInner` to put the annotation at the correct place, as is done on other similar places. This one attaches the annotation at the correct nesting level. > > Sadly, the code may be something very broken like: > > I i = @Ann foobar()::new; > > > and `insertAnnotationsToMostInner` would fail for this code/AST. Hence if the method reference is not over a type, we'll create an `AnnotatedType` (to keep the info in the AST as before) + an error + an error AST node. This pull request has now been integrated. Changeset: 8b536b54 Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/8b536b5428d5bf087dc71f3559c3978b13acad16 Stats: 249 lines in 4 files changed: 240 ins; 5 del; 4 mod 8369489: Marker annotation on inner class access crashes javac compiler Reviewed-by: vromero ------------- PR: https://git.openjdk.org/jdk/pull/27864 From cstein at openjdk.org Wed Nov 5 06:26:16 2025 From: cstein at openjdk.org (Christian Stein) Date: Wed, 5 Nov 2025 06:26:16 GMT Subject: Integrated: 8370175: State engine terminates when throwing self-caused exception In-Reply-To: References: Message-ID: On Wed, 29 Oct 2025 06:51:12 GMT, Christian Stein wrote: > Please review this change to prevent an engine termination in `jshell` in a self-causation exception scenario. > > Prior to the fix, a non-null cause exception was unconditionally converted and used. Now, a set with identity equalitiy semantics is guarding the process, by breaking a recursive chains when a reference cycle is detected. The guard implementation is inspired by the one used in [java.base/java.lang.Throwable](https://github.com/openjdk/jdk/blob/0687f120cc324f35fe43d811b6beb4184fd854ec/src/java.base/share/classes/java/lang/Throwable.java#L689-L693) > > Note that a direct self-causation state is already prevented at the `Throwable::initCause` method level: > > > jshell> var t = new Throwable() > t ==> java.lang.Throwable > > jshell> t.initCause(t) > | Exception java.lang.IllegalArgumentException: Self-causation not permitted > | at Throwable.initCause (Throwable.java:492) > | at (#8:1) > | Caused by: java.lang.Throwable > | at do_it$Aux (#7:1) > | at (#7:1) This pull request has now been integrated. Changeset: a0e70c4e Author: Christian Stein URL: https://git.openjdk.org/jdk/commit/a0e70c4e9489fc3d8f35c3aec9423fe0839ed0bd Stats: 30 lines in 2 files changed: 25 ins; 0 del; 5 mod 8370175: State engine terminates when throwing self-caused exception Reviewed-by: jlahoda, fandreuzzi ------------- PR: https://git.openjdk.org/jdk/pull/28037 From jpai at openjdk.org Wed Nov 5 07:35:00 2025 From: jpai at openjdk.org (Jaikiran Pai) Date: Wed, 5 Nov 2025 07:35:00 GMT Subject: RFR: 8365699: Remove jdk.internal.javac.PreviewFeature.Feature enum values for features finalized in Java 25 or earlier In-Reply-To: References: Message-ID: <_xpL77wWdAxgipvuOdMQqVMnhY2vMO8Yh3RDJYtdtMs=.5f233ff6-2357-4fed-9f77-2432d14290f6@github.com> On Tue, 4 Nov 2025 10:33:27 GMT, Jaikiran Pai wrote: > Can I please get a review of this change which cleans up the outdated enum constants in the internal `jdk.internal.javac.PreviewFeature$Feature` enum? > > This addresses https://bugs.openjdk.org/browse/JDK-8365699. As noted in that issue, this enum has accumulated some outdated preview feature constants which are no longer needed. The changes in this PR removes those enum constants whose preview features have been finalized in Java 25 or earlier (the current mainline bootstrap JDK is Java 25). A code comment explaining the lifetime of these enum constants has also been added. > > No new tests have been introduced and tier1, tier2, tier3 testing is currently in progress in the CI. tier1, tier2 and tier3 testing of this change completed without any failures. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28128#issuecomment-3489743887 From cushon at openjdk.org Wed Nov 5 07:49:42 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 5 Nov 2025 07:49:42 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v4] In-Reply-To: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Message-ID: > Hi, please consider this fix for [JDK-8370800: Downgrade cant.attach.type.annotations diagnostics to warnings](https://bugs.openjdk.org/browse/JDK-8370800). > > As discussed in the, this reduces the compatibility impact of these diagnostics for builds that deliberately omit transitive annotation dependencies, for example if they are only referenced through javadoc `@link` tags, or by frameworks that conditionally load the classes. > > The PR changes the existing error diagnostic to an unconditional warning. Another alternative would be to make it an optional xlint diagnostic, perhaps as part of `-Xlint:classfile`, or as another category. Liam Miller-Cushon has updated the pull request incrementally with five additional commits since the last revision: - Remove .swp file - Update tests - Handle completing multiple type annotations attributes on the same symbol - Defer attaching type annotations to completion - complete ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28018/files - new: https://git.openjdk.org/jdk/pull/28018/files/c65a7ac5..2781df57 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28018&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28018&range=02-03 Stats: 127 lines in 4 files changed: 108 ins; 4 del; 15 mod Patch: https://git.openjdk.org/jdk/pull/28018.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28018/head:pull/28018 PR: https://git.openjdk.org/jdk/pull/28018 From cushon at openjdk.org Wed Nov 5 07:49:43 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 5 Nov 2025 07:49:43 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v3] In-Reply-To: <_Pmfnuh7YT1oYG_mVTZXAuZ-dPIr1-m0YjKGMMI3-lg=.7cab1b2f-9385-4fa2-9141-02f748f30ab6@github.com> References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> <_Pmfnuh7YT1oYG_mVTZXAuZ-dPIr1-m0YjKGMMI3-lg=.7cab1b2f-9385-4fa2-9141-02f748f30ab6@github.com> Message-ID: On Wed, 29 Oct 2025 14:17:13 GMT, Liam Miller-Cushon wrote: >> Hi, please consider this fix for [JDK-8370800: Downgrade cant.attach.type.annotations diagnostics to warnings](https://bugs.openjdk.org/browse/JDK-8370800). >> >> As discussed in the, this reduces the compatibility impact of these diagnostics for builds that deliberately omit transitive annotation dependencies, for example if they are only referenced through javadoc `@link` tags, or by frameworks that conditionally load the classes. >> >> The PR changes the existing error diagnostic to an unconditional warning. Another alternative would be to make it an optional xlint diagnostic, perhaps as part of `-Xlint:classfile`, or as another category. > > Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: > > Update examples.not-yet.txt I added a comment to https://bugs.openjdk.org/browse/JDK-8370800 with some more analysis. I think the core of the new behaviour that is surprising and potentially undesirable is > javac is more eagerly completing symbols that are referenced in the API of any libraries referenced by the current compilation, if those APIs have type annotations I wonder if a better approach here is to continue to report `cant.attach.type.annotations` as an unconditional error, but to defer the work down by `addTypeAnnotationsToSymbol` until the symbol is completed, instead of doing it unconditionally when annotations are completed after reading the class. That would mean that if the only place javac needing a missing class was to attach type annotations, a regular compilation would succeed, but a compilation with an annotation processor that tried to read those type annotations would still get a `cant.attach.type.annotations` error. I have uploaded a new draft where `addTypeAnnotationsToSymbol` is deferred until the annotated symbol is completed. @lahodaj do you think that approach might have any merit? ------------- PR Comment: https://git.openjdk.org/jdk/pull/28018#issuecomment-3484432827 From jlahoda at openjdk.org Wed Nov 5 09:52:08 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 5 Nov 2025 09:52:08 GMT Subject: RFR: 8371133: Clarify the purpose of "src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties" [v2] In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 12:18:34 GMT, Volkan Yazici wrote: >> Document usage and purpose of `ct.properties`. > > Volkan Yazici has updated the pull request incrementally with one additional commit since the last revision: > > Apply review feedback Looks good to me, thanks! ------------- Marked as reviewed by jlahoda (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28123#pullrequestreview-3420929276 From cushon at openjdk.org Wed Nov 5 12:39:55 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 5 Nov 2025 12:39:55 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v5] In-Reply-To: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Message-ID: > Hi, please consider this fix for [JDK-8370800: Downgrade cant.attach.type.annotations diagnostics to warnings](https://bugs.openjdk.org/browse/JDK-8370800). > > As discussed in the, this reduces the compatibility impact of these diagnostics for builds that deliberately omit transitive annotation dependencies, for example if they are only referenced through javadoc `@link` tags, or by frameworks that conditionally load the classes. > > The PR changes the existing error diagnostic to an unconditional warning. Another alternative would be to make it an optional xlint diagnostic, perhaps as part of `-Xlint:classfile`, or as another category. Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: Chain completers ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28018/files - new: https://git.openjdk.org/jdk/pull/28018/files/2781df57..d78c3425 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28018&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28018&range=03-04 Stats: 23 lines in 1 file changed: 0 ins; 18 del; 5 mod Patch: https://git.openjdk.org/jdk/pull/28018.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28018/head:pull/28018 PR: https://git.openjdk.org/jdk/pull/28018 From vyazici at openjdk.org Wed Nov 5 13:05:20 2025 From: vyazici at openjdk.org (Volkan Yazici) Date: Wed, 5 Nov 2025 13:05:20 GMT Subject: RFR: 8371133: Clarify the purpose of "src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties" [v2] In-Reply-To: References: Message-ID: <8Lr9KCi7AOCxCyEfh_hNlk3AvFSuaRnBMWtpXEGt-vY=.83a7688c-7c23-4d82-8f48-c9844c697646@github.com> On Wed, 5 Nov 2025 09:49:08 GMT, Jan Lahoda wrote: >> Volkan Yazici has updated the pull request incrementally with one additional commit since the last revision: >> >> Apply review feedback > > Looks good to me, thanks! @lahodaj, thanks so much for the reviews. Tier1 looks clear. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28123#issuecomment-3491084965 From vyazici at openjdk.org Wed Nov 5 13:05:22 2025 From: vyazici at openjdk.org (Volkan Yazici) Date: Wed, 5 Nov 2025 13:05:22 GMT Subject: Integrated: 8371133: Clarify the purpose of "src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties" In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 08:46:50 GMT, Volkan Yazici wrote: > Document usage and purpose of `ct.properties`. This pull request has now been integrated. Changeset: f6f87bb6 Author: Volkan Yazici URL: https://git.openjdk.org/jdk/commit/f6f87bb6759c86d941453a1776e8abfdffc48183 Stats: 10 lines in 1 file changed: 9 ins; 0 del; 1 mod 8371133: Clarify the purpose of "src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties" Reviewed-by: jlahoda ------------- PR: https://git.openjdk.org/jdk/pull/28123 From jlahoda at openjdk.org Wed Nov 5 15:07:34 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 5 Nov 2025 15:07:34 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v2] In-Reply-To: <0D_jgs9w47rAKwt5Udla_7C1bfb7Moc14-Fr4RsTq64=.27341088-069f-4208-817e-7391e1348a54@github.com> References: <0D_jgs9w47rAKwt5Udla_7C1bfb7Moc14-Fr4RsTq64=.27341088-069f-4208-817e-7391e1348a54@github.com> Message-ID: On Mon, 3 Nov 2025 18:31:48 GMT, Archie Cobbs wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java line 4055: >> >>> 4053: int maximumShift; >>> 4054: switch (((OperatorSymbol)operator).opcode) { >>> 4055: case ByteCodes.ishl: >> >> Nit: use "modernized" switch - multiple case labels and `->`? > > We can combined the labels, but since we're setting _two_ values we can't use the `->` syntax. Fixed in 8044632727d. Having two assignments should not be a blocker for `->`, no? It ought to be enough to use `{}`: switch (((OperatorSymbol)operator).opcode) { case ByteCodes.ishl, ByteCodes.ishr, ByteCodes.iushr, ByteCodes.ishll, ByteCodes.ishrl, ByteCodes.iushrl -> { targetType = syms.intType; maximumShift = 32; } case ByteCodes.lshl, ByteCodes.lshr, ByteCodes.lushr, ByteCodes.lshll, ByteCodes.lshrl, ByteCodes.lushrl -> { targetType = syms.longType; maximumShift = 64; } default -> { return; } } I am not strictly insisting on using `->`, but it generally makes things simpler as there's guaranteed no fallthrough. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2494960651 From jlahoda at openjdk.org Wed Nov 5 15:17:06 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 5 Nov 2025 15:17:06 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v2] In-Reply-To: References: <0D_jgs9w47rAKwt5Udla_7C1bfb7Moc14-Fr4RsTq64=.27341088-069f-4208-817e-7391e1348a54@github.com> Message-ID: On Wed, 5 Nov 2025 15:05:09 GMT, Jan Lahoda wrote: >> We can combined the labels, but since we're setting _two_ values we can't use the `->` syntax. Fixed in 8044632727d. > > Having two assignments should not be a blocker for `->`, no? It ought to be enough to use `{}`: > > switch (((OperatorSymbol)operator).opcode) { > case ByteCodes.ishl, ByteCodes.ishr, ByteCodes.iushr, > ByteCodes.ishll, ByteCodes.ishrl, ByteCodes.iushrl -> { > targetType = syms.intType; > maximumShift = 32; > } > case ByteCodes.lshl, ByteCodes.lshr, ByteCodes.lushr, > ByteCodes.lshll, ByteCodes.lshrl, ByteCodes.lushrl -> { > targetType = syms.longType; > maximumShift = 64; > } > default -> { > return; > } > } > > > I am not strictly insisting on using `->`, but it generally makes things simpler as there's guaranteed no fallthrough. The `->` can be used, even when having general statements/multiple assignments/etc. - just wrap the code with `{}`, no? switch (((OperatorSymbol)operator).opcode) { case ByteCodes.ishl, ByteCodes.ishr, ByteCodes.iushr, ByteCodes.ishll, ByteCodes.ishrl, ByteCodes.iushrl -> { targetType = syms.intType; maximumShift = 32; } case ByteCodes.lshl, ByteCodes.lshr, ByteCodes.lushr, ByteCodes.lshll, ByteCodes.lshrl, ByteCodes.lushrl -> { targetType = syms.longType; maximumShift = 64; } default -> { return; } } I am not strictly insisting on using `->` but it is typically easier to reason about switches that are guaranteed to not have fallthrough. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2495005451 From acobbs at openjdk.org Wed Nov 5 15:26:10 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 5 Nov 2025 15:26:10 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v3] In-Reply-To: References: Message-ID: > When bit shifting an `int` or `long` value by an amount `X`, all but the last 5 or 6 (respectively) bits of `X` are ignored. > > This can create a trap for the unwary, as in this example: > > public long readLongBigEndian(byte[] buf, int offset) { > return ((buf[offset + 0] & 0xff) << 56) // BUG HERE > | ((buf[offset + 1] & 0xff) << 48) // BUG HERE > | ((buf[offset + 2] & 0xff) << 40) // BUG HERE > | ((buf[offset + 3] & 0xff) << 32) // BUG HERE > | ((buf[offset + 4] & 0xff) << 24) > | ((buf[offset + 5] & 0xff) << 16) > | ((buf[offset + 6] & 0xff) << 8) > | ((buf[offset + 7] & 0xff); > } > > This PR adds a new warning when the compiler detects an out-of-range bit shift, i.e., an `int` bit shift not in the range `[0...31]` or a `long` bit shift not in the range `[0...63]`. Archie Cobbs has updated the pull request incrementally with two additional commits since the last revision: - Use -> in switch statement. - Update copyright year. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27102/files - new: https://git.openjdk.org/jdk/pull/27102/files/021e0fb3..89fe2fb1 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27102&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27102&range=01-02 Stats: 7 lines in 2 files changed: 1 ins; 0 del; 6 mod Patch: https://git.openjdk.org/jdk/pull/27102.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27102/head:pull/27102 PR: https://git.openjdk.org/jdk/pull/27102 From acobbs at openjdk.org Wed Nov 5 15:26:11 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 5 Nov 2025 15:26:11 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v3] In-Reply-To: References: <0D_jgs9w47rAKwt5Udla_7C1bfb7Moc14-Fr4RsTq64=.27341088-069f-4208-817e-7391e1348a54@github.com> Message-ID: On Wed, 5 Nov 2025 15:14:49 GMT, Jan Lahoda wrote: >> Having two assignments should not be a blocker for `->`, no? It ought to be enough to use `{}`: >> >> switch (((OperatorSymbol)operator).opcode) { >> case ByteCodes.ishl, ByteCodes.ishr, ByteCodes.iushr, >> ByteCodes.ishll, ByteCodes.ishrl, ByteCodes.iushrl -> { >> targetType = syms.intType; >> maximumShift = 32; >> } >> case ByteCodes.lshl, ByteCodes.lshr, ByteCodes.lushr, >> ByteCodes.lshll, ByteCodes.lshrl, ByteCodes.lushrl -> { >> targetType = syms.longType; >> maximumShift = 64; >> } >> default -> { >> return; >> } >> } >> >> >> I am not strictly insisting on using `->`, but it generally makes things simpler as there's guaranteed no fallthrough. > > The `->` can be used, even when having general statements/multiple assignments/etc. - just wrap the code with `{}`, no? > > > switch (((OperatorSymbol)operator).opcode) { > case ByteCodes.ishl, ByteCodes.ishr, ByteCodes.iushr, > ByteCodes.ishll, ByteCodes.ishrl, ByteCodes.iushrl -> { > targetType = syms.intType; > maximumShift = 32; > } > case ByteCodes.lshl, ByteCodes.lshr, ByteCodes.lushr, > ByteCodes.lshll, ByteCodes.lshrl, ByteCodes.lushrl -> { > targetType = syms.longType; > maximumShift = 64; > } > default -> { > return; > } > } > > > I am not strictly insisting on using `->` but it is typically easier to reason about switches that are guaranteed to not have fallthrough. > Having two assignments should not be a blocker for `->`, no? It ought to be enough to use `{}`: Duh - of course you're right. Fixed in 89fe2fb1f93. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2495043399 From jlahoda at openjdk.org Wed Nov 5 15:28:57 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 5 Nov 2025 15:28:57 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v3] In-Reply-To: References: Message-ID: On Mon, 3 Nov 2025 19:12:43 GMT, Roger Riggs wrote: >> Hmm, obviously this is a judgement call and I'm curious what others think. >> >> My opinion is that I still think there should be a warning for shifts of -1. >> >> I mean, maybe to a _real_ hacker, then of course `foo << -1` makes perfect sense because it's just stating the "obvious" which is "shift the low order bit into the high order position and set all the other bits to zero", right?? :) >> >> I just don't think the average Java programmer automatically understands that. >> >> Yes, it's an idiom or "handy trick", but if hasn't attained the status of being universally recognized then it doesn't deserve a special exception. >> >> On the other hand, excluding -1 from the warning would be less disruptive (at least, to the real hackers out there), and that has its own merits. So I don't have a super strong opinion about it. > > This might be worth a corpus scan to see how common it is to shift by -1 or other constants, either int or long. > Someone, might interpret `v << -1` as a right shift, is it more likely to misinterpret it as using more than 5/6 bits of the shift or considering it signed. I am working on a corpus run, will take some days probably. But I am not sure if producing a warning for code that is "correct, but advanced use" is realistic. Maybe the line needs to be draw closer to "the code is probably buggy/highly suspicious". @rgiulietti - thanks, the explanation makes sense. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2495062625 From acobbs at openjdk.org Wed Nov 5 15:41:07 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 5 Nov 2025 15:41:07 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v3] In-Reply-To: References: Message-ID: On Wed, 5 Nov 2025 15:26:31 GMT, Jan Lahoda wrote: > Maybe the line needs to be draw closer to "the code is probably buggy/highly suspicious". I'm OK with this more conservative approach, which should satisfy all the "real hackers": instead of warning for values outside of the range `[0,n)` (where `n` is 32 or 64), only warn for values outside of the range `(-n, n)`. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2495106722 From prappo at openjdk.org Wed Nov 5 16:05:45 2025 From: prappo at openjdk.org (Pavel Rappo) Date: Wed, 5 Nov 2025 16:05:45 GMT Subject: RFR: 8155591: Misleading warning when not overriding close method in interface extending AutoCloseable [v2] In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 10:56:24 GMT, Jan Lahoda wrote: >> Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains two additional commits since the last revision: >> >> - Merge branch 'master' into JDK-8155591 to get recent build fixes. >> - Don't warn about AutoCloseable.close() itself throwing InterruptedException. > > Makes sense to me. I think it would be useful if the tests would be enhanced to cover the case where the `close` method declaration in non-AutoClo does actually `Exception`/`InterruptedException`. I found `InterruptedExceptionTest.java`, but as that's a combo test, it is harder to see a sensible warning is produced on a sensible place. > > Regarding sensible place, it would be possible to produce a warning specifically at the problematic `close` method (if it is declared in the given class, and not inherited) using `TreeInfo.diagnosticPositionFor`, but it is not so easy in this case - among other things, the warning would probably need a different wording. Up to you. > Hi @lahodaj thanks for taking a look. > > I just realized there is another potential issue. Shouldn't a warning also be generated in this example? > > ```java > class WithClose { > public void close() throws Exception { } > } > public class Try extends WithClose implements AutoCloseable { } > ``` > > Currently the compiler does not generate one; I'm not sure yet what exact logical tweak would be needed. Good catch! WithClose.close() does override AutoCloseable.close() from Try. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27062#issuecomment-3492055450 From cushon at openjdk.org Wed Nov 5 18:22:18 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 5 Nov 2025 18:22:18 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v6] In-Reply-To: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Message-ID: <3jZJh2YgPmAiGyLSR0z8qXQdDSMGcyjQhKfa2hCbAlc=.b5d6d4fc-e40c-4b6f-90d3-a05223ba307b@github.com> > Hi, please consider this fix for [JDK-8370800: Downgrade cant.attach.type.annotations diagnostics to warnings](https://bugs.openjdk.org/browse/JDK-8370800). > > As discussed in the, this reduces the compatibility impact of these diagnostics for builds that deliberately omit transitive annotation dependencies, for example if they are only referenced through javadoc `@link` tags, or by frameworks that conditionally load the classes. > > The PR changes the existing error diagnostic to an unconditional warning. Another alternative would be to make it an optional xlint diagnostic, perhaps as part of `-Xlint:classfile`, or as another category. Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: Only lazily complete type annotations for members, not classes ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28018/files - new: https://git.openjdk.org/jdk/pull/28018/files/d78c3425..74512b21 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28018&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28018&range=04-05 Stats: 9 lines in 1 file changed: 5 ins; 1 del; 3 mod Patch: https://git.openjdk.org/jdk/pull/28018.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28018/head:pull/28018 PR: https://git.openjdk.org/jdk/pull/28018 From acobbs at openjdk.org Wed Nov 5 18:23:27 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 5 Nov 2025 18:23:27 GMT Subject: RFR: 8155591: Misleading warning when not overriding close method in interface extending AutoCloseable [v3] In-Reply-To: References: Message-ID: <3IVkx2jW7a37ll1Io8Kof-kJQJ3J7xU7B-o6lZLZcbA=.d27e93fb-72d0-4083-9027-d11d2c47f356@github.com> > The compiler generates a warning if you declare a `close()` method that throws any supertype of `InterruptedException` in a class or interface extending `AutoCloseable`. This is because suppressed `InterruptedException`'s are likely to lead to misbehavior at runtime. > > However, this feature also generates a warning due to `AutoCloseable.close()` itself, if you simply inherit it. For example: > > $ cat MyClass.java > public interface MyClass extends AutoCloseable { > } > $ javac -Xlint:try MyClass.java > MyClass.java:1: warning: [try] auto-closeable resource MyClass has a member method close() that could throw InterruptedException > public interface MyClass extends AutoCloseable { > ^ > 1 warning > > The warning is not useful because `AutoCloseable.close()` is abstract and so it's going to be some other class' job to deal with the throws clause. > > This change prevents `AutoCloseable.close()` itself from triggering the warning in a class declaration. We preserve the existing behavior in which a warning is generated at the use site (i.e., at the try-with-resources statement). Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains five additional commits since the last revision: - Add more regression test variants. - Fix missed warning when close() method implemented in superclass. - Merge branch 'master' into JDK-8155591 - Merge branch 'master' into JDK-8155591 to get recent build fixes. - Don't warn about AutoCloseable.close() itself throwing InterruptedException. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27062/files - new: https://git.openjdk.org/jdk/pull/27062/files/3f769967..d9b78c60 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27062&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27062&range=01-02 Stats: 129414 lines in 2312 files changed: 73962 ins; 40822 del; 14630 mod Patch: https://git.openjdk.org/jdk/pull/27062.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27062/head:pull/27062 PR: https://git.openjdk.org/jdk/pull/27062 From jlahoda at openjdk.org Wed Nov 5 18:50:42 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 5 Nov 2025 18:50:42 GMT Subject: RFR: 8155591: Misleading warning when not overriding close method in interface extending AutoCloseable [v3] In-Reply-To: <3IVkx2jW7a37ll1Io8Kof-kJQJ3J7xU7B-o6lZLZcbA=.d27e93fb-72d0-4083-9027-d11d2c47f356@github.com> References: <3IVkx2jW7a37ll1Io8Kof-kJQJ3J7xU7B-o6lZLZcbA=.d27e93fb-72d0-4083-9027-d11d2c47f356@github.com> Message-ID: On Wed, 5 Nov 2025 18:23:27 GMT, Archie Cobbs wrote: >> The compiler generates a warning if you declare a `close()` method that throws any supertype of `InterruptedException` in a class or interface extending `AutoCloseable`. This is because suppressed `InterruptedException`'s are likely to lead to misbehavior at runtime. >> >> However, this feature also generates a warning due to `AutoCloseable.close()` itself, if you simply inherit it. For example: >> >> $ cat MyClass.java >> public interface MyClass extends AutoCloseable { >> } >> $ javac -Xlint:try MyClass.java >> MyClass.java:1: warning: [try] auto-closeable resource MyClass has a member method close() that could throw InterruptedException >> public interface MyClass extends AutoCloseable { >> ^ >> 1 warning >> >> The warning is not useful because `AutoCloseable.close()` is abstract and so it's going to be some other class' job to deal with the throws clause. >> >> This change prevents `AutoCloseable.close()` itself from triggering the warning in a class declaration. We preserve the existing behavior in which a warning is generated at the use site (i.e., at the try-with-resources statement). > > Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains five additional commits since the last revision: > > - Add more regression test variants. > - Fix missed warning when close() method implemented in superclass. > - Merge branch 'master' into JDK-8155591 > - Merge branch 'master' into JDK-8155591 to get recent build fixes. > - Don't warn about AutoCloseable.close() itself throwing InterruptedException. Looks OK to me. @jddarcy - looks good to me - any comments/insights? Thanks! ------------- Marked as reviewed by jlahoda (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27062#pullrequestreview-3423786292 PR Comment: https://git.openjdk.org/jdk/pull/27062#issuecomment-3492796340 From jlahoda at openjdk.org Wed Nov 5 19:19:50 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 5 Nov 2025 19:19:50 GMT Subject: RFR: 8340840: jshell ClassFormatError when making inner class static [v5] In-Reply-To: References: Message-ID: <1aSIFXYHwYLRa1I2XHRuoiL8CLPwQyOLx3yBNxt6GqI=.c1d373c6-3a34-4d32-9a1a-e1d64f5a45de@github.com> > Consider a JShell interaction like: > > jshell> class O { class I {} } > | created class O > > jshell> var i = new O().new I(); > i ==> O$I at 77caeb3e > > jshell> class O { static class I {} } > Exception in thread "main" java.lang.ClassFormatError: class not in class file format > at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396) > at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90) > at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120) > at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) > at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722) > at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) > at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) > at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) > at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) > at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121) > at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213) > at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193) > at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206) > at jdk.jshell/jdk.jshell.TaskFactory.compile(TaskFactory.java:186) > at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100) > at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901) > at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140) > at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.run(JShellTool.java:... Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Adapting the warning message as suggested on the CSR. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27665/files - new: https://git.openjdk.org/jdk/pull/27665/files/6914c146..a0fe9b65 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27665&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27665&range=03-04 Stats: 2 lines in 1 file changed: 1 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/27665.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27665/head:pull/27665 PR: https://git.openjdk.org/jdk/pull/27665 From acobbs at openjdk.org Wed Nov 5 21:19:03 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 5 Nov 2025 21:19:03 GMT Subject: RFR: 8155591: Misleading warning when not overriding close method in interface extending AutoCloseable [v2] In-Reply-To: References: Message-ID: <9ynNepNMnG_TK6HJWAeK4DC67nW8ysLLrkJe78bbgkE=.488d2abc-7a90-44b3-931c-1a132150e572@github.com> On Tue, 4 Nov 2025 10:56:24 GMT, Jan Lahoda wrote: > Makes sense to me. I think it would be useful if the tests would be enhanced to cover the case where the `close` method declaration in non-AutoClo does actually `Exception`/`InterruptedException`. I found `InterruptedExceptionTest.java`, but as that's a combo test, it is harder to see a sensible warning is produced on a sensible place. Good idea - added in d9b78c60242. > Regarding sensible place, it would be possible to produce a warning specifically at the problematic `close` method (if it is declared in the given class, and not inherited) using `TreeInfo.diagnosticPositionFor`, but it is not so easy in this case - among other things, the warning would probably need a different wording. Up to you. I agree that would be better: if a declaration is what's causing the warning to be generated, then the warning should be located at that declaration. Since you already approved this PR, I've implemented that last idea in an [alternate branch](https://github.com/archiecobbs/jdk/compare/JDK-8155591...archiecobbs:jdk:JDK-8155591-alt1). Take a look and let me know if you prefer that, or want to stick with what's already approved. Thanks! ------------- PR Comment: https://git.openjdk.org/jdk/pull/27062#issuecomment-3493506216 From vromero at openjdk.org Wed Nov 5 23:26:06 2025 From: vromero at openjdk.org (Vicente Romero) Date: Wed, 5 Nov 2025 23:26:06 GMT Subject: RFR: 8365699: Remove jdk.internal.javac.PreviewFeature.Feature enum values for features finalized in Java 25 or earlier In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 10:33:27 GMT, Jaikiran Pai wrote: > Can I please get a review of this change which cleans up the outdated enum constants in the internal `jdk.internal.javac.PreviewFeature$Feature` enum? > > This addresses https://bugs.openjdk.org/browse/JDK-8365699. As noted in that issue, this enum has accumulated some outdated preview feature constants which are no longer needed. The changes in this PR removes those enum constants whose preview features have been finalized in Java 25 or earlier (the current mainline bootstrap JDK is Java 25). A code comment explaining the lifetime of these enum constants has also been added. > > No new tests have been introduced and tier1, tier2, tier3 testing is currently in progress in the CI. lgtm ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28128#pullrequestreview-3424936525 From liach at openjdk.org Wed Nov 5 23:34:14 2025 From: liach at openjdk.org (Chen Liang) Date: Wed, 5 Nov 2025 23:34:14 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v20] In-Reply-To: References: Message-ID: On Fri, 24 Oct 2025 09:01:10 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Rework toString implementations src/java.base/share/classes/java/lang/LazyConstant.java line 94: > 92: * lazy constant remains uninitialized. > 93: * > 94: *

Composing lazy constants

This section has some interesting usage, but I don't believe it should be included in the API specification. Behaviors described here can be derived from the formal specifications. src/java.base/share/classes/java/lang/LazyConstant.java line 209: > 207: > 208: /** > 209: * {@return the contents of this lazy constant if initialized, otherwise,\ Suggestion: * {@return the contents of this lazy constant if initialized, otherwise, src/java.base/share/classes/java/util/AbstractMap.java line 34: > 32: > 33: import jdk.internal.vm.annotation.AOTSafeClassInitializer; > 34: import jdk.internal.vm.annotation.Stable; Suggestion: src/java.base/share/classes/java/util/Currency.java line 146: > 144: private static ConcurrentMap instances = new ConcurrentHashMap<>(7); > 145: private static final LazyConstant> available = > 146: LazyConstant.of(new Supplier>() { Why can't we retain the method reference here? This is not used in early bootstrap. src/java.base/share/classes/java/util/LazyCollections.java line 516: > 514: > 515: @ForceInline > 516: private void disposeOfMutex(long offset) { I recommend removing this unused and otherwise confusing method. src/java.base/share/classes/java/util/LazyCollections.java line 559: > 557: } > 558: > 559: public static int lastIndexOf(List> list, Object o) { This indexOf and lastIndexOf appear unused. src/java.base/share/classes/java/util/Map.java line 1814: > 1812: final Set keyCopies = Set.copyOf(keys); > 1813: Objects.requireNonNull(computingFunction); > 1814: if (keys instanceof EnumSet && !keys.isEmpty()) { I wonder if it's premature for us to optimize like this - for example, this would be wasteful if the key set contains one enum constant but there are 1000 enum constants in this enum. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2496459406 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2496468213 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2496478562 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2496479687 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2496503928 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2496514844 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2496516750 From duke at openjdk.org Wed Nov 5 23:47:04 2025 From: duke at openjdk.org (ExE Boss) Date: Wed, 5 Nov 2025 23:47:04 GMT Subject: RFR: 8155591: Misleading warning when not overriding close method in interface extending AutoCloseable [v3] In-Reply-To: <3IVkx2jW7a37ll1Io8Kof-kJQJ3J7xU7B-o6lZLZcbA=.d27e93fb-72d0-4083-9027-d11d2c47f356@github.com> References: <3IVkx2jW7a37ll1Io8Kof-kJQJ3J7xU7B-o6lZLZcbA=.d27e93fb-72d0-4083-9027-d11d2c47f356@github.com> Message-ID: On Wed, 5 Nov 2025 18:23:27 GMT, Archie Cobbs wrote: >> The compiler generates a warning if you declare a `close()` method that throws any supertype of `InterruptedException` in a class or interface extending `AutoCloseable`. This is because suppressed `InterruptedException`'s are likely to lead to misbehavior at runtime. >> >> However, this feature also generates a warning due to `AutoCloseable.close()` itself, if you simply inherit it. For example: >> >> $ cat MyClass.java >> public interface MyClass extends AutoCloseable { >> } >> $ javac -Xlint:try MyClass.java >> MyClass.java:1: warning: [try] auto-closeable resource MyClass has a member method close() that could throw InterruptedException >> public interface MyClass extends AutoCloseable { >> ^ >> 1 warning >> >> The warning is not useful because `AutoCloseable.close()` is abstract and so it's going to be some other class' job to deal with the throws clause. >> >> This change prevents `AutoCloseable.close()` itself from triggering the warning in a class declaration. We preserve the existing behavior in which a warning is generated at the use site (i.e., at the try-with-resources statement). > > Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains five additional commits since the last revision: > > - Add more regression test variants. > - Fix missed warning when close() method implemented in superclass. > - Merge branch 'master' into JDK-8155591 > - Merge branch 'master' into JDK-8155591 to get recent build fixes. > - Don't warn about AutoCloseable.close() itself throwing InterruptedException. test/langtools/tools/javac/TryWithResources/InterruptedExceptionTest2.java line 92: > 90: } > 91: > 92: abstract class InterruptedExceptionTest_C10 extends WithClose implements AutoCloseable { // warning here What?about the?case when?`WithClose` is?replaced?with an?`abstract?class` with?an?`abstract void?close()` method?declaration? abstract class WithAbstractClose { public abstract void close() throws Exception; } abstract class InterruptedExceptionTest_C11 extends WithAbstractClose implements AutoCloseable { } ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27062#discussion_r2496525853 From liach at openjdk.org Wed Nov 5 23:51:01 2025 From: liach at openjdk.org (Chen Liang) Date: Wed, 5 Nov 2025 23:51:01 GMT Subject: RFR: 8365699: Remove jdk.internal.javac.PreviewFeature.Feature enum values for features finalized in Java 25 or earlier In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 10:33:27 GMT, Jaikiran Pai wrote: > Can I please get a review of this change which cleans up the outdated enum constants in the internal `jdk.internal.javac.PreviewFeature$Feature` enum? > > This addresses https://bugs.openjdk.org/browse/JDK-8365699. As noted in that issue, this enum has accumulated some outdated preview feature constants which are no longer needed. The changes in this PR removes those enum constants whose preview features have been finalized in Java 25 or earlier (the current mainline bootstrap JDK is Java 25). A code comment explaining the lifetime of these enum constants has also been added. > > No new tests have been introduced and tier1, tier2, tier3 testing is currently in progress in the CI. Marked as reviewed by liach (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/28128#pullrequestreview-3424994084 From acobbs at openjdk.org Thu Nov 6 02:53:47 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Thu, 6 Nov 2025 02:53:47 GMT Subject: RFR: 8155591: Misleading warning when not overriding close method in interface extending AutoCloseable [v4] In-Reply-To: References: Message-ID: > The compiler generates a warning if you declare a `close()` method that throws any supertype of `InterruptedException` in a class or interface extending `AutoCloseable`. This is because suppressed `InterruptedException`'s are likely to lead to misbehavior at runtime. > > However, this feature also generates a warning due to `AutoCloseable.close()` itself, if you simply inherit it. For example: > > $ cat MyClass.java > public interface MyClass extends AutoCloseable { > } > $ javac -Xlint:try MyClass.java > MyClass.java:1: warning: [try] auto-closeable resource MyClass has a member method close() that could throw InterruptedException > public interface MyClass extends AutoCloseable { > ^ > 1 warning > > The warning is not useful because `AutoCloseable.close()` is abstract and so it's going to be some other class' job to deal with the throws clause. > > This change prevents `AutoCloseable.close()` itself from triggering the warning in a class declaration. We preserve the existing behavior in which a warning is generated at the use site (i.e., at the try-with-resources statement). Archie Cobbs has updated the pull request incrementally with three additional commits since the last revision: - Add another regression test case. - Unbreak existing regression test after previous commit. - Show warnings for declared close() at declaration site. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27062/files - new: https://git.openjdk.org/jdk/pull/27062/files/d9b78c60..b79b5951 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27062&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27062&range=02-03 Stats: 72 lines in 6 files changed: 27 ins; 0 del; 45 mod Patch: https://git.openjdk.org/jdk/pull/27062.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27062/head:pull/27062 PR: https://git.openjdk.org/jdk/pull/27062 From acobbs at openjdk.org Thu Nov 6 02:53:47 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Thu, 6 Nov 2025 02:53:47 GMT Subject: RFR: 8155591: Misleading warning when not overriding close method in interface extending AutoCloseable [v3] In-Reply-To: References: <3IVkx2jW7a37ll1Io8Kof-kJQJ3J7xU7B-o6lZLZcbA=.d27e93fb-72d0-4083-9027-d11d2c47f356@github.com> Message-ID: On Wed, 5 Nov 2025 23:36:27 GMT, ExE Boss wrote: > What about the case when `WithClose` is replaced with an `abstract class` with an `abstract void close()` method declaration? Thanks, I've added that as well. No warning in that case, because the `close()` method is not concrete so the problem hasn't become "real" yet. Since this forces a re-review, I'll also merged in the fix to put the warning on the method instead of the class as mentioned above. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27062#discussion_r2496917557 From liach at openjdk.org Thu Nov 6 03:23:04 2025 From: liach at openjdk.org (Chen Liang) Date: Thu, 6 Nov 2025 03:23:04 GMT Subject: RFR: 8340840: jshell ClassFormatError when making inner class static [v5] In-Reply-To: <1aSIFXYHwYLRa1I2XHRuoiL8CLPwQyOLx3yBNxt6GqI=.c1d373c6-3a34-4d32-9a1a-e1d64f5a45de@github.com> References: <1aSIFXYHwYLRa1I2XHRuoiL8CLPwQyOLx3yBNxt6GqI=.c1d373c6-3a34-4d32-9a1a-e1d64f5a45de@github.com> Message-ID: <8MkrmO_QCPpyB6aLvS2azwtPvs87gL68a-qc8vNZ2rE=.5425ccd1-d675-45b4-92fb-dcfb2ecd1f9a@github.com> On Wed, 5 Nov 2025 19:19:50 GMT, Jan Lahoda wrote: >> Consider a JShell interaction like: >> >> jshell> class O { class I {} } >> | created class O >> >> jshell> var i = new O().new I(); >> i ==> O$I at 77caeb3e >> >> jshell> class O { static class I {} } >> Exception in thread "main" java.lang.ClassFormatError: class not in class file format >> at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396) >> at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90) >> at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312) >> at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120) >> at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) >> at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722) >> at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) >> at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) >> at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) >> at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) >> at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) >> at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) >> at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) >> at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121) >> at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213) >> at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193) >> at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206) >> at jdk.jshell/jdk.jshell.TaskFactory.compile(TaskFactory.java:186) >> at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100) >> at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901) >> at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140) >> at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251) >> ... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Adapting the warning message as suggested on the CSR. The new warning looks good. ------------- Marked as reviewed by liach (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27665#pullrequestreview-3425655127 From jpai at openjdk.org Thu Nov 6 04:45:10 2025 From: jpai at openjdk.org (Jaikiran Pai) Date: Thu, 6 Nov 2025 04:45:10 GMT Subject: RFR: 8365699: Remove jdk.internal.javac.PreviewFeature.Feature enum values for features finalized in Java 25 or earlier In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 10:33:27 GMT, Jaikiran Pai wrote: > Can I please get a review of this change which cleans up the outdated enum constants in the internal `jdk.internal.javac.PreviewFeature$Feature` enum? > > This addresses https://bugs.openjdk.org/browse/JDK-8365699. As noted in that issue, this enum has accumulated some outdated preview feature constants which are no longer needed. The changes in this PR removes those enum constants whose preview features have been finalized in Java 25 or earlier (the current mainline bootstrap JDK is Java 25). A code comment explaining the lifetime of these enum constants has also been added. > > No new tests have been introduced and tier1, tier2, tier3 testing is currently in progress in the CI. Thank you Vicente and Chen for the reviews. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28128#issuecomment-3495007919 From jpai at openjdk.org Thu Nov 6 04:45:11 2025 From: jpai at openjdk.org (Jaikiran Pai) Date: Thu, 6 Nov 2025 04:45:11 GMT Subject: Integrated: 8365699: Remove jdk.internal.javac.PreviewFeature.Feature enum values for features finalized in Java 25 or earlier In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 10:33:27 GMT, Jaikiran Pai wrote: > Can I please get a review of this change which cleans up the outdated enum constants in the internal `jdk.internal.javac.PreviewFeature$Feature` enum? > > This addresses https://bugs.openjdk.org/browse/JDK-8365699. As noted in that issue, this enum has accumulated some outdated preview feature constants which are no longer needed. The changes in this PR removes those enum constants whose preview features have been finalized in Java 25 or earlier (the current mainline bootstrap JDK is Java 25). A code comment explaining the lifetime of these enum constants has also been added. > > No new tests have been introduced and tier1, tier2, tier3 testing is currently in progress in the CI. This pull request has now been integrated. Changeset: 188da51f Author: Jaikiran Pai URL: https://git.openjdk.org/jdk/commit/188da51f30e5ca3945fee91fe2e94f0466151c06 Stats: 23 lines in 1 file changed: 15 ins; 6 del; 2 mod 8365699: Remove jdk.internal.javac.PreviewFeature.Feature enum values for features finalized in Java 25 or earlier Reviewed-by: vromero, liach ------------- PR: https://git.openjdk.org/jdk/pull/28128 From darcy at openjdk.org Thu Nov 6 05:02:15 2025 From: darcy at openjdk.org (Joe Darcy) Date: Thu, 6 Nov 2025 05:02:15 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v20] In-Reply-To: References: Message-ID: On Fri, 24 Oct 2025 09:01:10 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Rework toString implementations src/java.base/share/classes/java/lang/LazyConstant.java line 184: > 182: * Use in static initializers may interact with class initialization order; > 183: * cyclic initialization may result in initialization errors as described > 184: * in {@jls 12.4} of The Java Language Specification. Please use some text like "section" or "§" in from of the `@jls` tag. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2497396558 From asotona at openjdk.org Thu Nov 6 07:50:09 2025 From: asotona at openjdk.org (Adam Sotona) Date: Thu, 6 Nov 2025 07:50:09 GMT Subject: RFR: 8340840: jshell ClassFormatError when making inner class static [v5] In-Reply-To: <1aSIFXYHwYLRa1I2XHRuoiL8CLPwQyOLx3yBNxt6GqI=.c1d373c6-3a34-4d32-9a1a-e1d64f5a45de@github.com> References: <1aSIFXYHwYLRa1I2XHRuoiL8CLPwQyOLx3yBNxt6GqI=.c1d373c6-3a34-4d32-9a1a-e1d64f5a45de@github.com> Message-ID: On Wed, 5 Nov 2025 19:19:50 GMT, Jan Lahoda wrote: >> Consider a JShell interaction like: >> >> jshell> class O { class I {} } >> | created class O >> >> jshell> var i = new O().new I(); >> i ==> O$I at 77caeb3e >> >> jshell> class O { static class I {} } >> Exception in thread "main" java.lang.ClassFormatError: class not in class file format >> at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396) >> at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90) >> at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312) >> at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120) >> at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) >> at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722) >> at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) >> at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) >> at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) >> at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) >> at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) >> at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) >> at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) >> at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121) >> at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213) >> at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193) >> at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206) >> at jdk.jshell/jdk.jshell.TaskFactory.compile(TaskFactory.java:186) >> at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100) >> at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901) >> at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140) >> at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251) >> ... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Adapting the warning message as suggested on the CSR. Marked as reviewed by asotona (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27665#pullrequestreview-3426701335 From jlahoda at openjdk.org Thu Nov 6 09:38:02 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 6 Nov 2025 09:38:02 GMT Subject: RFR: 8340840: jshell ClassFormatError when making inner class static [v6] In-Reply-To: References: Message-ID: > Consider a JShell interaction like: > > jshell> class O { class I {} } > | created class O > > jshell> var i = new O().new I(); > i ==> O$I at 77caeb3e > > jshell> class O { static class I {} } > Exception in thread "main" java.lang.ClassFormatError: class not in class file format > at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396) > at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90) > at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120) > at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) > at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722) > at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) > at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) > at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) > at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) > at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121) > at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213) > at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193) > at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206) > at jdk.jshell/jdk.jshell.TaskFactory.compile(TaskFactory.java:186) > at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100) > at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901) > at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140) > at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.run(JShellTool.java:... Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Wrapping the detail message with parenthesis as suggested. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27665/files - new: https://git.openjdk.org/jdk/pull/27665/files/a0fe9b65..eee81509 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27665&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27665&range=04-05 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/27665.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27665/head:pull/27665 PR: https://git.openjdk.org/jdk/pull/27665 From jlahoda at openjdk.org Thu Nov 6 11:02:17 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 6 Nov 2025 11:02:17 GMT Subject: RFR: 8155591: Misleading warning when not overriding close method in interface extending AutoCloseable [v4] In-Reply-To: References: Message-ID: On Thu, 6 Nov 2025 02:53:47 GMT, Archie Cobbs wrote: >> The compiler generates a warning if you declare a `close()` method that throws any supertype of `InterruptedException` in a class or interface extending `AutoCloseable`. This is because suppressed `InterruptedException`'s are likely to lead to misbehavior at runtime. >> >> However, this feature also generates a warning due to `AutoCloseable.close()` itself, if you simply inherit it. For example: >> >> $ cat MyClass.java >> public interface MyClass extends AutoCloseable { >> } >> $ javac -Xlint:try MyClass.java >> MyClass.java:1: warning: [try] auto-closeable resource MyClass has a member method close() that could throw InterruptedException >> public interface MyClass extends AutoCloseable { >> ^ >> 1 warning >> >> The warning is not useful because `AutoCloseable.close()` is abstract and so it's going to be some other class' job to deal with the throws clause. >> >> This change prevents `AutoCloseable.close()` itself from triggering the warning in a class declaration. We preserve the existing behavior in which a warning is generated at the use site (i.e., at the try-with-resources statement). > > Archie Cobbs has updated the pull request incrementally with three additional commits since the last revision: > > - Add another regression test case. > - Unbreak existing regression test after previous commit. > - Show warnings for declared close() at declaration site. Looks good to me. ------------- Marked as reviewed by jlahoda (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27062#pullrequestreview-3427566595 From cushon at openjdk.org Thu Nov 6 11:32:34 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Thu, 6 Nov 2025 11:32:34 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v7] In-Reply-To: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Message-ID: > Hi, please consider this fix for [JDK-8370800: Downgrade cant.attach.type.annotations diagnostics to warnings](https://bugs.openjdk.org/browse/JDK-8370800). > > As discussed in the, this reduces the compatibility impact of these diagnostics for builds that deliberately omit transitive annotation dependencies, for example if they are only referenced through javadoc `@link` tags, or by frameworks that conditionally load the classes. > > The PR changes the existing error diagnostic to an unconditional warning. Another alternative would be to make it an optional xlint diagnostic, perhaps as part of `-Xlint:classfile`, or as another category. Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: Adjust tests ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28018/files - new: https://git.openjdk.org/jdk/pull/28018/files/74512b21..39c4741f Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28018&range=06 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28018&range=05-06 Stats: 27 lines in 1 file changed: 15 ins; 1 del; 11 mod Patch: https://git.openjdk.org/jdk/pull/28018.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28018/head:pull/28018 PR: https://git.openjdk.org/jdk/pull/28018 From cushon at openjdk.org Thu Nov 6 11:32:35 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Thu, 6 Nov 2025 11:32:35 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v3] In-Reply-To: References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> <_Pmfnuh7YT1oYG_mVTZXAuZ-dPIr1-m0YjKGMMI3-lg=.7cab1b2f-9385-4fa2-9141-02f748f30ab6@github.com> Message-ID: On Tue, 4 Nov 2025 08:07:12 GMT, Liam Miller-Cushon wrote: > I wonder if a better approach here is to continue to report `cant.attach.type.annotations` as an unconditional error, but to defer the work down by `addTypeAnnotationsToSymbol` until the symbol is completed, instead of doing it unconditionally when annotations are completed after reading the class. I have been doing some more testing with this and it seems to work. I adjusted the initial approach to ensure it's only deferring attaching type annotations to symbol completion for non-class members, classes are still completed eagerly, which has the desired behaviour for type annotations and also avoids interactions with how annotation processing resets completers for class symbols. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28018#issuecomment-3496706390 From acobbs at openjdk.org Thu Nov 6 15:28:02 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Thu, 6 Nov 2025 15:28:02 GMT Subject: RFR: 8155591: Misleading warning when not overriding close method in interface extending AutoCloseable [v3] In-Reply-To: References: <3IVkx2jW7a37ll1Io8Kof-kJQJ3J7xU7B-o6lZLZcbA=.d27e93fb-72d0-4083-9027-d11d2c47f356@github.com> Message-ID: <-Fc_GYHsi-s8E4uJaXTqIoSXUD7Hn3YENJfxCGx3tzU=.dde61b46-a274-46e7-a6a4-6f4818cf7dc0@github.com> On Wed, 5 Nov 2025 18:47:54 GMT, Jan Lahoda wrote: >> Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains five additional commits since the last revision: >> >> - Add more regression test variants. >> - Fix missed warning when close() method implemented in superclass. >> - Merge branch 'master' into JDK-8155591 >> - Merge branch 'master' into JDK-8155591 to get recent build fixes. >> - Don't warn about AutoCloseable.close() itself throwing InterruptedException. > > @jddarcy - looks good to me - any comments/insights? Thanks! @lahodaj thanks for the review! ------------- PR Comment: https://git.openjdk.org/jdk/pull/27062#issuecomment-3497802397 From acobbs at openjdk.org Thu Nov 6 15:31:29 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Thu, 6 Nov 2025 15:31:29 GMT Subject: Integrated: 8155591: Misleading warning when not overriding close method in interface extending AutoCloseable In-Reply-To: References: Message-ID: On Tue, 2 Sep 2025 23:35:52 GMT, Archie Cobbs wrote: > The compiler generates a warning if you declare a `close()` method that throws any supertype of `InterruptedException` in a class or interface extending `AutoCloseable`. This is because suppressed `InterruptedException`'s are likely to lead to misbehavior at runtime. > > However, this feature also generates a warning due to `AutoCloseable.close()` itself, if you simply inherit it. For example: > > $ cat MyClass.java > public interface MyClass extends AutoCloseable { > } > $ javac -Xlint:try MyClass.java > MyClass.java:1: warning: [try] auto-closeable resource MyClass has a member method close() that could throw InterruptedException > public interface MyClass extends AutoCloseable { > ^ > 1 warning > > The warning is not useful because `AutoCloseable.close()` is abstract and so it's going to be some other class' job to deal with the throws clause. > > This change prevents `AutoCloseable.close()` itself from triggering the warning in a class declaration. We preserve the existing behavior in which a warning is generated at the use site (i.e., at the try-with-resources statement). This pull request has now been integrated. Changeset: a5864582 Author: Archie Cobbs URL: https://git.openjdk.org/jdk/commit/a5864582da7e19b941bf55c294a414bc1a0c7a84 Stats: 306 lines in 6 files changed: 300 ins; 0 del; 6 mod 8155591: Misleading warning when not overriding close method in interface extending AutoCloseable Reviewed-by: jlahoda ------------- PR: https://git.openjdk.org/jdk/pull/27062 From mcimadamore at openjdk.org Thu Nov 6 16:05:22 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 6 Nov 2025 16:05:22 GMT Subject: RFR: 8340840: jshell ClassFormatError when making inner class static [v6] In-Reply-To: References: Message-ID: On Thu, 6 Nov 2025 09:38:02 GMT, Jan Lahoda wrote: >> Consider a JShell interaction like: >> >> jshell> class O { class I {} } >> | created class O >> >> jshell> var i = new O().new I(); >> i ==> O$I at 77caeb3e >> >> jshell> class O { static class I {} } >> Exception in thread "main" java.lang.ClassFormatError: class not in class file format >> at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396) >> at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90) >> at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312) >> at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120) >> at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) >> at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722) >> at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) >> at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) >> at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) >> at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) >> at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) >> at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) >> at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) >> at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121) >> at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213) >> at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193) >> at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206) >> at jdk.jshell/jdk.jshell.TaskFactory.compile(TaskFactory.java:186) >> at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100) >> at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901) >> at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140) >> at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251) >> ... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Wrapping the detail message with parenthesis as suggested. Marked as reviewed by mcimadamore (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27665#pullrequestreview-3429052646 From acobbs at openjdk.org Thu Nov 6 17:26:35 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Thu, 6 Nov 2025 17:26:35 GMT Subject: RFR: 8371162: Compiler warns about implicit cast from long to int in shift operation Message-ID: Consider code like this: int x = 1; x <<= 1L; The compiler currently emits this warning: warning: [lossy-conversions] implicit cast from long to int in compound assignment is possibly lossy x <<= 1L; ^ By definition, bit shift operations only use the bottom 5 or 6 bits of the specified shift amount (in this example, `1L`), and the JLS does not require the shift amount to be any specific integral type, only that that it be some integral type. So as long all but the bottom 5 or 6 bits are zero, there is no loss of information and the warning is inappropriate. The case where the bottom 5 or 6 bits are _not_ all zero is addressed separately in [JDK-5038439](https://bugs.openjdk.org/browse/JDK-5038439). ------------- Commit messages: - Avoid lossy conversion warnings for 64 bit shift amounts. Changes: https://git.openjdk.org/jdk/pull/28180/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28180&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8371162 Stats: 44 lines in 2 files changed: 43 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/28180.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28180/head:pull/28180 PR: https://git.openjdk.org/jdk/pull/28180 From jlahoda at openjdk.org Thu Nov 6 20:45:14 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 6 Nov 2025 20:45:14 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v4] In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 15:47:46 GMT, Aggelos Biboudis wrote: >> Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 23 commits: >> >> - Merge branch 'JDK-8364991' into JDK-8367530 >> - Fixing tests >> - Merge branch 'JDK-8364991-2' into JDK-8367530-2 >> - Better visualisation. >> - Merge branch 'JDK-8367499' into JDK-8367530 >> - Merge branch 'JDK-8364991' into JDK-8367499 >> - Fixing tests. >> - Cleanup. >> - Cleanup. >> - Cleanup. >> - ... and 13 more: https://git.openjdk.org/jdk/compare/e6a3f0da...b7c33349 > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 351: > >> 349: Type instantiated = instantiatePatternType(targetType, csym); >> 350: >> 351: return instantiated != null && types.isCastable(targetType, instantiated); > > If inference fails, does this mean that we get an exhaustiveness error with a sample generic instantiation? If the inference fails, then the subtype won't be considered as necessary to cover the supertype, is it is an "impossible" type. For example, the code in this test: https://github.com/openjdk/jdk/blob/8a0c47d4ba4db523d94689b3ac347e9cd35183ce/test/langtools/tools/javac/patterns/Exhaustiveness.java#L914 > I wonder how can we end up here with completely incompatible classes? (final A, final B) (so that the castability check return false in `isPossibleSubtypePredicate`). Wouldn't that be an error of applicability? The exact point of `isPossibleSubtypePredicate` (here and in the existing exhaustiveness computation) is to not consider cases that would not be applicable. Like for example here: https://github.com/openjdk/jdk/blob/8a0c47d4ba4db523d94689b3ac347e9cd35183ce/test/langtools/tools/javac/patterns/Exhaustiveness.java#L1663 Neither `A_I1` nor `B_I2` are applicable, and hence we don't need to consider them when computing exhaustiveness. They will fail the castability check, and the exhaustiveness algorithm will not consider them when computing coverage for `Z`. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2500794798 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2500784792 From acobbs at openjdk.org Thu Nov 6 21:03:01 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Thu, 6 Nov 2025 21:03:01 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v4] In-Reply-To: References: Message-ID: <7G0o3Ph7D9I11xzojJwIXuJ4nHvNtXtQpy2BdfuZ6Kw=.b1766068-44ad-4a74-ac51-b37b191c3e65@github.com> > When bit shifting an `int` or `long` value by an amount `X`, all but the last 5 or 6 (respectively) bits of `X` are ignored. > > This can create a trap for the unwary, as in this example: > > public long readLongBigEndian(byte[] buf, int offset) { > return ((buf[offset + 0] & 0xff) << 56) // BUG HERE > | ((buf[offset + 1] & 0xff) << 48) // BUG HERE > | ((buf[offset + 2] & 0xff) << 40) // BUG HERE > | ((buf[offset + 3] & 0xff) << 32) // BUG HERE > | ((buf[offset + 4] & 0xff) << 24) > | ((buf[offset + 5] & 0xff) << 16) > | ((buf[offset + 6] & 0xff) << 8) > | ((buf[offset + 7] & 0xff); > } > > This PR adds a new warning when the compiler detects an out-of-range bit shift, i.e., an `int` bit shift not in the range `[0...31]` or a `long` bit shift not in the range `[0...63]`. Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: Don't warn for negative shift values that are otherwise in range. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27102/files - new: https://git.openjdk.org/jdk/pull/27102/files/89fe2fb1..4156e813 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27102&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27102&range=02-03 Stats: 69 lines in 6 files changed: 13 ins; 5 del; 51 mod Patch: https://git.openjdk.org/jdk/pull/27102.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27102/head:pull/27102 PR: https://git.openjdk.org/jdk/pull/27102 From acobbs at openjdk.org Thu Nov 6 21:03:02 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Thu, 6 Nov 2025 21:03:02 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v4] In-Reply-To: References: Message-ID: On Wed, 5 Nov 2025 15:37:54 GMT, Archie Cobbs wrote: > > Maybe the line needs to be draw closer to "the code is probably buggy/highly suspicious". > > I'm OK with this more conservative approach, which should satisfy all the "real hackers": instead of warning for values outside of the range `[0,n)` (where `n` is 32 or 64), only warn for values outside of the range `(-n, n)`. I went ahead and updated this PR and the CSR to not warn about negative shifts that are otherwise in range. Please take a look at both and let me know what you guys think. We can always turn the screws harder in the future if appropriate. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2500850339 From jlahoda at openjdk.org Fri Nov 7 09:10:16 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 7 Nov 2025 09:10:16 GMT Subject: Integrated: 8340840: jshell ClassFormatError when making inner class static In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 07:15:50 GMT, Jan Lahoda wrote: > Consider a JShell interaction like: > > jshell> class O { class I {} } > | created class O > > jshell> var i = new O().new I(); > i ==> O$I at 77caeb3e > > jshell> class O { static class I {} } > Exception in thread "main" java.lang.ClassFormatError: class not in class file format > at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396) > at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90) > at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120) > at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) > at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722) > at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) > at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) > at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) > at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) > at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121) > at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213) > at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193) > at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206) > at jdk.jshell/jdk.jshell.TaskFactory.compile(TaskFactory.java:186) > at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100) > at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901) > at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140) > at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.run(JShellTool.java:... This pull request has now been integrated. Changeset: 205a163a Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/205a163a90bb263d403476c28203836189e337a7 Stats: 367 lines in 8 files changed: 352 ins; 0 del; 15 mod 8340840: jshell ClassFormatError when making inner class static 8368999: jshell crash when existing sealed class is updated to also be abstract Reviewed-by: mcimadamore, asotona, liach ------------- PR: https://git.openjdk.org/jdk/pull/27665 From cstein at openjdk.org Fri Nov 7 09:49:33 2025 From: cstein at openjdk.org (Christian Stein) Date: Fri, 7 Nov 2025 09:49:33 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file Message-ID: Please review this change to include a validation check for expecting an optional JAR manifest entry being the first or second entry in JAR file. As the second entry, it must be only preceeded by an entry for the `META-INF/` directory. ------------- Commit messages: - Compact implementation - Inline method - Manifest is optional, no need to add it here - 8268613: jar --validate should check inital entries of a JAR file Changes: https://git.openjdk.org/jdk/pull/28154/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28154&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8268613 Stats: 95 lines in 3 files changed: 95 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/28154.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28154/head:pull/28154 PR: https://git.openjdk.org/jdk/pull/28154 From jlahoda at openjdk.org Fri Nov 7 09:55:12 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 7 Nov 2025 09:55:12 GMT Subject: RFR: 8278856: javac documentation does not mention use of Manifest class-path attribute [v2] In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 16:49:31 GMT, Christian Stein wrote: >> Please review this improvement to `javac`'s manpage, section **Directory Hierarchies**. > > Christian Stein has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains two additional commits since the last revision: > > - Merge branch 'openjdk:master' into patch-2 > - 8278856: javac documentation does not mention use of Manifest class-path attribute Looks reasonable. ------------- Marked as reviewed by jlahoda (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/22243#pullrequestreview-3432670325 From jlahoda at openjdk.org Fri Nov 7 09:56:44 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 7 Nov 2025 09:56:44 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v5] In-Reply-To: References: Message-ID: > Consider code like: > > package test; > public class Test { > private int test(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > ``` > > This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > The goal of this PR is to improve the error, at least in some cases to something along these lines: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > missing patterns: > test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) > 1 error > > > The (very simplified) way it works in a recursive (or induction) way: > - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. > - for a current missing pattern, try to enhance it: > - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. > - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. > > This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. > > There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. > > Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. > > There's also an open possibility for select tools to delay the more detailed computation to some later time, although that would need to be tried and eval... Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Reflecting review comments. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27256/files - new: https://git.openjdk.org/jdk/pull/27256/files/b7c33349..50ddab0f Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=03-04 Stats: 117 lines in 1 file changed: 48 ins; 40 del; 29 mod Patch: https://git.openjdk.org/jdk/pull/27256.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27256/head:pull/27256 PR: https://git.openjdk.org/jdk/pull/27256 From cstein at openjdk.org Fri Nov 7 09:58:12 2025 From: cstein at openjdk.org (Christian Stein) Date: Fri, 7 Nov 2025 09:58:12 GMT Subject: Integrated: 8278856: javac documentation does not mention use of Manifest class-path attribute In-Reply-To: References: Message-ID: On Tue, 19 Nov 2024 16:06:23 GMT, Christian Stein wrote: > Please review this improvement to `javac`'s manpage, section **Directory Hierarchies**. This pull request has now been integrated. Changeset: 428b553a Author: Christian Stein URL: https://git.openjdk.org/jdk/commit/428b553ad4ee79e5d56f51232c27ed0b003abe18 Stats: 6 lines in 1 file changed: 6 ins; 0 del; 0 mod 8278856: javac documentation does not mention use of Manifest class-path attribute Reviewed-by: jlahoda ------------- PR: https://git.openjdk.org/jdk/pull/22243 From jlahoda at openjdk.org Fri Nov 7 13:32:29 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 7 Nov 2025 13:32:29 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v4] In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 13:08:04 GMT, Aggelos Biboudis wrote: >> Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 23 commits: >> >> - Merge branch 'JDK-8364991' into JDK-8367530 >> - Fixing tests >> - Merge branch 'JDK-8364991-2' into JDK-8367530-2 >> - Better visualisation. >> - Merge branch 'JDK-8367499' into JDK-8367530 >> - Merge branch 'JDK-8364991' into JDK-8367499 >> - Fixing tests. >> - Cleanup. >> - Cleanup. >> - Cleanup. >> - ... and 13 more: https://git.openjdk.org/jdk/compare/e6a3f0da...b7c33349 > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 173: > >> 171: } >> 172: >> 173: private CoverageResult computeCoverage(Type selectorType, Set patterns, boolean search) { > > This extra boolean parameter is subtle (because previously we didn't have a new mode of execution). Can you introduce either a top-level comment at the `computeCoverage` method or something more descriptive than `search` or an enumeration with the two modes? Because now it is calculating both the coverage result and the inverse (uncovered patterns). I've introduced `PatternEquivalence`, and tried to document the use. > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 893: > >> 891: >> 892: for (Type componentType : componentTypes) { >> 893: List variants; > > Is this the same conceptually to `viablePermittedPatterns` for the binding patterns case? If yes, we can reuse the same name (just to match the concepts)? I've adjusted the variable name. > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 924: > >> 922: .collect(Collectors.toCollection(HashSet::new)); >> 923: >> 924: //remove unnecessary: > > It seems that the removal of the unnecessary patterns is common to the next step as well? If yes, would it be beneficial to extract? Done, extracted. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2503539624 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2503546230 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2503542592 From jlahoda at openjdk.org Fri Nov 7 13:32:30 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 7 Nov 2025 13:32:30 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v4] In-Reply-To: References: Message-ID: On Thu, 6 Nov 2025 20:40:16 GMT, Jan Lahoda wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 836: >> >>> 834: if (toExpand instanceof BindingPattern bp) { >>> 835: if (bp.type.tsym.isSealed()) { >>> 836: //try to replace binding patterns for sealed types with all their immediate permitted types: >> >> Can you reuse the word "viablePermittedPatterns" in this comment? That way the reader can formulate the properties of what this variable represents, faster. >> >> IIUC this is a process of minimization going from the `viablePermittedPatterns` to `reducedPermittedPatterns`. Not only that, but (I think) there is a property that reduction means that you prune the combinatorial space as long as there are no variables *and* the pattern is the most general. The actual invariants are actually coming from `isPossibleSubtypePredicate` which ensures castability and pattern inference. >> >> I wonder how can we end up here with completely incompatible classes? (final A, final B) (so that the castability check return false in `isPossibleSubtypePredicate`). Wouldn't that be an error of applicability? > >> I wonder how can we end up here with completely incompatible classes? (final A, final B) (so that the castability check return false in `isPossibleSubtypePredicate`). Wouldn't that be an error of applicability? > > The exact point of `isPossibleSubtypePredicate` (here and in the existing exhaustiveness computation) is to not consider cases that would not be applicable. Like for example here: > https://github.com/openjdk/jdk/blob/8a0c47d4ba4db523d94689b3ac347e9cd35183ce/test/langtools/tools/javac/patterns/Exhaustiveness.java#L1663 > > Neither `A_I1` nor `B_I2` are applicable, and hence we don't need to consider them when computing exhaustiveness. They will fail the castability check, and the exhaustiveness algorithm will not consider them when computing coverage for `Z`. I've changed the variable name, and adjusted the comment. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2503544943 From jlahoda at openjdk.org Fri Nov 7 13:32:32 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 7 Nov 2025 13:32:32 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v4] In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 14:14:46 GMT, Aggelos Biboudis wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 948: >> >>> 946: //combine sealed subtypes into the supertype, if all is covered. >>> 947: //but preserve more specific record types in positions where there are record patterns in the original patterns >>> 948: //this is particularly for the case where the sealed supertype only has one permitted type, the record >> >> There is a word missing:"this is particularly *important* for" I think, right? > > Interesting. This is a property for NR-1S that shows up here too. Nice. Done. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2503546791 From jlahoda at openjdk.org Fri Nov 7 13:40:11 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 7 Nov 2025 13:40:11 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v4] In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 13:16:45 GMT, Aggelos Biboudis wrote: >> Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 23 commits: >> >> - Merge branch 'JDK-8364991' into JDK-8367530 >> - Fixing tests >> - Merge branch 'JDK-8364991-2' into JDK-8367530-2 >> - Better visualisation. >> - Merge branch 'JDK-8367499' into JDK-8367530 >> - Merge branch 'JDK-8364991' into JDK-8367499 >> - Fixing tests. >> - Cleanup. >> - Cleanup. >> - Cleanup. >> - ... and 13 more: https://git.openjdk.org/jdk/compare/e6a3f0da...b7c33349 > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 157: > >> 155: .stream() >> 156: .flatMap(pd -> { >> 157: if (pd instanceof BindingPattern bp && enum2Constants.containsKey(bp.type.tsym)) { > > Can this be subsumed into `computeMissingPatternDescriptions` just to handle the generation of all kinds of incomplete patterns inside there? It seems to be that this client-side would be clearer, but ignore if it would be too much fuss. I was thinking of this, and given where I think this code is heading with new features added, I think I would prefer to keep it as it is for now. I do agree it would be better if `computeMissingPatterDescriptions` would return the exact missing patterns including missing enum constants, but I think the more appropriate way to do it is using a pattern description for enum constant, and we are not there yet. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2503592163 From jlahoda at openjdk.org Fri Nov 7 13:40:05 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 7 Nov 2025 13:40:05 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v5] In-Reply-To: References: Message-ID: On Fri, 7 Nov 2025 09:56:44 GMT, Jan Lahoda wrote: >> Consider code like: >> >> package test; >> public class Test { >> private int test(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> ``` >> >> This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> The goal of this PR is to improve the error, at least in some cases to something along these lines: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> missing patterns: >> test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) >> 1 error >> >> >> The (very simplified) way it works in a recursive (or induction) way: >> - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. >> - for a current missing pattern, try to enhance it: >> - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. >> - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. >> >> This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. >> >> There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. >> >> Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. >> >> There's also an open possibility for select tools to... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Reflecting review comments. Thanks for the comments so far. I think I've updated the code where needed based on them, and tried to respond. Thanks! ------------- PR Comment: https://git.openjdk.org/jdk/pull/27256#issuecomment-3502619550 From cushon at openjdk.org Fri Nov 7 20:28:02 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Fri, 7 Nov 2025 20:28:02 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v7] In-Reply-To: References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Message-ID: On Thu, 6 Nov 2025 11:32:34 GMT, Liam Miller-Cushon wrote: >> Hi, please consider this fix for [JDK-8370800: Downgrade cant.attach.type.annotations diagnostics to warnings](https://bugs.openjdk.org/browse/JDK-8370800). >> >> As discussed in the, this reduces the compatibility impact of these diagnostics for builds that deliberately omit transitive annotation dependencies, for example if they are only referenced through javadoc `@link` tags, or by frameworks that conditionally load the classes. >> >> The PR changes the existing error diagnostic to an unconditional warning. Another alternative would be to make it an optional xlint diagnostic, perhaps as part of `-Xlint:classfile`, or as another category. > > Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: > > Adjust tests I have realized this approach doesn't work for all cases, because there are public APIs that allow accessing type annotations on an `ExecutableElement` that don't result in the underlying `MethodSymbol` getting completed. It would be possible to fix that by ensuring that methods like `MethodSymbol#asType` call `complete()`. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28018#issuecomment-3504775392 From arnoldnunag12 at gmail.com Sat Nov 8 21:41:15 2025 From: arnoldnunag12 at gmail.com (Arnold Alejo Nunag) Date: Sun, 9 Nov 2025 05:41:15 +0800 Subject: Lambdas do not copy over SYNTHETIC flag for local variables Message-ID: <336141c5-0d05-44a6-8398-de04df56cf7e@gmail.com> Hello, A project which I help out with recently discovered a bug with regards to lambdas; specifically, local variables within lambdas (or more specifically, their synthetic generated methods) never have the SYNTHETIC flag, even if the same source outside of a lambda would emit local variables with the SYNTHETIC flag. The bug occurs on openjdk version "25.0.1" 2025-10-21 LTS. Examples of source that emit SYNTHETIC-marked local variables are enhanced-for loops operating on arrays, and (what prompted our discovery) pattern-matching instanceof. I tested the same bug on Java 17 (17.0.14) and 21 (21.0.9), and it occurs for the pattern-matching instanceof. Interesting, testing with an array enhanced-for shows that the bug occurs only on 25, but not for 21, 17, or 8. This bug originates from https://git.openjdk.org/jdk/commit/cf30c203379008ebae37bf00f1839a69cd53ca26 and https://git.openjdk.org/jdk/commit/360461f13671495c07ab9881284f24191ecc3525, where only the FINAL flag is copied over for local variables when translating code for lambdas. The following source when disassembled demonstrates the problem: /// BEGIN SOURCE public class Test { ? ? private void test_noLambda() { ? ? ? ? if (getThing() instanceof Number number) { ? ? ? ? ? ? System.out.println(number); ? ? ? ? } ? ? } ? ? private void test_withLambda() { ? ? ? ? Runnable run = () -> { ? ? ? ? ? ? if (getThing() instanceof Number number) { ? ? ? ? ? ? ? ? System.out.println(number); ? ? ? ? ? ? } ? ? ? ? }; ? ? } ? ? private Object getThing() { ? ? ? ? return null; ? ? } } /// END SOURCE 1. Compile the above class using `javac -g:vars Test.java`. 2. Run `javap -p -c -l Test.class`. The expected result is that both `test_noLambda` and `lambda$test_withLambda$0` should have the same local variable table with two slots: `number` and `this`. The actual result is that `lambda$test_withLambda$0` has one extra local variable: `patt0$temp`. As the name implies, that belongs to the pattern-matching instanceof. I have found a potential fix through the following patch (though I have not yet fully tested this): diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index b13c9e0fe2b..41554dae432 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -1152,7 +1152,7 @@ VarSymbol translate(final VarSymbol sym, LambdaSymbolKind skind) { propagateAnnos = false; break; case LOCAL_VAR: - ret = new VarSymbol(sym.flags() & FINAL, sym.name, sym.type, translatedSym); + ret = new VarSymbol(sym.flags() & (SYNTHETIC | FINAL), sym.name, sym.type, translatedSym); ret.pos = sym.pos; // If sym.data == ElementKind.EXCEPTION_PARAMETER, // set ret.data = ElementKind.EXCEPTION_PARAMETER too. I'd like to contribute the above fix myself, if possible. I've already submitted my OCA (pending approval). I believe my next step is to file a bug through https://bugs.java/, which I'll do within a few days (or if someone tells me to). Thank you! ~ Arnold Alejo Nunag, @sciwhiz12 -------------- next part -------------- An HTML attachment was scrubbed... URL: From cushon at openjdk.org Sun Nov 9 18:30:53 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Sun, 9 Nov 2025 18:30:53 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v8] In-Reply-To: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Message-ID: > Hi, please consider this fix for [JDK-8370800: Downgrade cant.attach.type.annotations diagnostics to warnings](https://bugs.openjdk.org/browse/JDK-8370800). > > As discussed in the, this reduces the compatibility impact of these diagnostics for builds that deliberately omit transitive annotation dependencies, for example if they are only referenced through javadoc `@link` tags, or by frameworks that conditionally load the classes. > > The PR changes the existing error diagnostic to an unconditional warning. Another alternative would be to make it an optional xlint diagnostic, perhaps as part of `-Xlint:classfile`, or as another category. Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: Complete symbols returned by getAllMembers ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28018/files - new: https://git.openjdk.org/jdk/pull/28018/files/39c4741f..ecad620d Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28018&range=07 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28018&range=06-07 Stats: 3 lines in 1 file changed: 2 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/28018.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28018/head:pull/28018 PR: https://git.openjdk.org/jdk/pull/28018 From cushon at openjdk.org Sun Nov 9 18:30:55 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Sun, 9 Nov 2025 18:30:55 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v7] In-Reply-To: References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Message-ID: On Fri, 7 Nov 2025 20:25:46 GMT, Liam Miller-Cushon wrote: > I have realized this approach doesn't work for all cases, because there are public APIs that allow accessing type annotations on an `ExecutableElement` that don't result in the underlying `MethodSymbol` getting completed In particular, `JavacElements#getAllMembers` doesn't complete the elements it returns. `Element#getEnclosedElements` _does_ complete the members it returns, and many annotation processors use `#getEnclosedElements` to get `ExecutableElement`s they process, which partly explains why this was working in many cases. `getAllMembers` could be updated to do completion, but there may be other paths that return `ExecutableElement`s that would need similar updates, the way that methods that return or operate on class symbols all ensure the class has been completed. in general I'm still unsure if using the completion mechanism for `MethodSymbol` is an acceptable approach. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28018#issuecomment-3508660661 From alanb at openjdk.org Mon Nov 10 10:41:03 2025 From: alanb at openjdk.org (Alan Bateman) Date: Mon, 10 Nov 2025 10:41:03 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file In-Reply-To: References: Message-ID: On Wed, 5 Nov 2025 17:29:10 GMT, Christian Stein wrote: > Please review this change to include a validation check for expecting an optional JAR manifest entry being the first or second entry in JAR file. As the second entry, it must be only preceeded by an entry for the `META-INF/` directory. src/jdk.jartool/share/classes/sun/tools/jar/Validator.java line 257: > 255: errorAndInvalid(formatMsg("error.validator.wrong.position", firstName, "0")); > 256: } > 257: } This looks right, except that `entryInfo.cen().order()` is confusing to read. At some point we need to re-visit EntryEncounter and EntryInfo as the naming is very confusing. The cen member suggests it returns the CEN, and the order member is confusing too. Maybe ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28154#discussion_r2509860450 From pminborg at openjdk.org Mon Nov 10 11:11:05 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 10 Nov 2025 11:11:05 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v21] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 107 commits: - Merge master - Rework toString implementations - Update after doc comments - Merge branch 'master' into lazy-constants - Revert the AbstractMap.keySet @Stable annotation - Update docs after comments - Improve method docs - Improve equals/hashCode document - Update wording on List/Map Object methods - Update javadocs - ... and 97 more: https://git.openjdk.org/jdk/compare/681dab72...f775aaf1 ------------- Changes: https://git.openjdk.org/jdk/pull/27605/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=20 Stats: 8482 lines in 60 files changed: 3875 ins; 4490 del; 117 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Mon Nov 10 11:17:43 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 10 Nov 2025 11:17:43 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v22] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Fix merge mistake ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/f775aaf1..003eaf1c Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=21 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=20-21 Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Mon Nov 10 12:36:12 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 10 Nov 2025 12:36:12 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v20] In-Reply-To: References: Message-ID: On Wed, 5 Nov 2025 23:31:38 GMT, Chen Liang wrote: >> Per Minborg has updated the pull request incrementally with one additional commit since the last revision: >> >> Rework toString implementations > > src/java.base/share/classes/java/util/Map.java line 1814: > >> 1812: final Set keyCopies = Set.copyOf(keys); >> 1813: Objects.requireNonNull(computingFunction); >> 1814: if (keys instanceof EnumSet && !keys.isEmpty()) { > > I wonder if it's premature for us to optimize like this - for example, this would be wasteful if the key set contains one enum constant but there are 1000 enum constants in this enum. There is a `min` and a `max` ordinal calculated, so in your example above, only one array item is used. I.e., if there are 1,000 enum constant and we are using enum with ordinal 42, then min = max = 42 and only a one-element array is ever allocated. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2510377932 From pminborg at openjdk.org Mon Nov 10 13:00:35 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 10 Nov 2025 13:00:35 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v23] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Address comments in PR ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/003eaf1c..03616ef6 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=22 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=21-22 Stats: 119 lines in 6 files changed: 17 ins; 72 del; 30 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From jvernee at openjdk.org Mon Nov 10 13:58:50 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Mon, 10 Nov 2025 13:58:50 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file In-Reply-To: References: Message-ID: <0kXR9LUYkpot1AJkkAk659sl0To-INwK5nOwR9wxozI=.9c076fb1-04d9-4e54-89ef-28c48c30f3b1@github.com> On Wed, 5 Nov 2025 17:29:10 GMT, Christian Stein wrote: > Please review this change to include a validation check for expecting an optional JAR manifest entry being the first or second entry in JAR file. As the second entry, it must be only preceeded by an entry for the `META-INF/` directory. test/jdk/tools/jar/ValidatorTest.java line 354: > 352: jar("--validate --file " + path); > 353: fail("Expecting non-zero exit code validating: " + path); > 354: } catch (IOException e) { It's just that `jar` method that throws the expected exception, right? Could you limit the length of the `try` block to not cover the nested try block? Otherwise, if `JarInputStream` starts throwing the same exception, this test would stop testing the `jar` method. (also I think it makes it a little clearer which line is expected to throw) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28154#discussion_r2510675268 From pminborg at openjdk.org Mon Nov 10 14:59:03 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 10 Nov 2025 14:59:03 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v24] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Add @AOTSafeClassInitializer ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/03616ef6..e479cb4b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=23 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=22-23 Stats: 5 lines in 2 files changed: 5 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From nbenalla at openjdk.org Mon Nov 10 16:15:38 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Mon, 10 Nov 2025 16:15:38 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 [v4] In-Reply-To: References: Message-ID: <_XezcddmMuD5koE3C1dJPmKhQGSfPHvi0tNBwaUv7oI=.0ffc5492-ca89-43ef-ac6c-b3e44bc11255@github.com> > Get JDK 27 underway. Nizar Benalla has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains six additional commits since the last revision: - Updates due to the generate-symbol-data.sh location changing in 8367259 - Updates due to the generate-symbol-data.sh location changing in 8367259 - Merge branch 'master' into start-of-release-27 - update links to JVMS 26 and 27 - add missing enum - initial commit start-of-JDK-27 ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28130/files - new: https://git.openjdk.org/jdk/pull/28130/files/b51f2324..0652d5d3 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=02-03 Stats: 164507 lines in 1034 files changed: 112814 ins; 23251 del; 28442 mod Patch: https://git.openjdk.org/jdk/pull/28130.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28130/head:pull/28130 PR: https://git.openjdk.org/jdk/pull/28130 From iris at openjdk.org Mon Nov 10 16:35:13 2025 From: iris at openjdk.org (Iris Clark) Date: Mon, 10 Nov 2025 16:35:13 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 [v4] In-Reply-To: <_XezcddmMuD5koE3C1dJPmKhQGSfPHvi0tNBwaUv7oI=.0ffc5492-ca89-43ef-ac6c-b3e44bc11255@github.com> References: <_XezcddmMuD5koE3C1dJPmKhQGSfPHvi0tNBwaUv7oI=.0ffc5492-ca89-43ef-ac6c-b3e44bc11255@github.com> Message-ID: <4hRkyQC_Dpj1ojQuuFvjJEkFiFqCHqDQm_nnPjDRxfc=.c0a10797-cb7a-4987-9574-0b570acd21b0@github.com> On Mon, 10 Nov 2025 16:15:38 GMT, Nizar Benalla wrote: >> Get JDK 27 underway. > > Nizar Benalla has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains six additional commits since the last revision: > > - Updates due to the generate-symbol-data.sh location changing in 8367259 > - Updates due to the generate-symbol-data.sh location changing in 8367259 > - Merge branch 'master' into start-of-release-27 > - update links to JVMS 26 and 27 > - add missing enum > - initial commit start-of-JDK-27 Expected changes for JDK 27 looking good. make/conf/version-numbers.conf line 36: > 34: DEFAULT_VERSION_EXTRA2=0 > 35: DEFAULT_VERSION_EXTRA3=0 > 36: DEFAULT_VERSION_DATE=2026-09-15 Anticipated GA date confirmed. ------------- PR Review: https://git.openjdk.org/jdk/pull/28130#pullrequestreview-3444133407 PR Review Comment: https://git.openjdk.org/jdk/pull/28130#discussion_r2511223183 From archie.cobbs at gmail.com Mon Nov 10 19:45:03 2025 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Mon, 10 Nov 2025 13:45:03 -0600 Subject: Classfile type annotation for CAST expressions Message-ID: Could someone help me confirm whether the following behavior is incorrect, or just under-specified? Consider this code: import java.lang.annotation.*; public class DoubleCast { DoubleCast(Object o) { o = (DoubleCast & @Anno Runnable)o; } } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) @interface Anno { } There is an @Anno type annotation on the second class in the cast expression (Runnable), so we expect to find that noted in the RuntimeVisibleTypeAnnotations classfile attribute. Because the cast involves an intersection type, the bytecode will have two CHECKCAST instructions, as shown in the javap output: DoubleCast(java.lang.Object); descriptor: (Ljava/lang/Object;)V flags: (0x0000) Code: stack=1, locals=2, args_size=2 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: aload_1 5: checkcast #7 // class java/lang/Runnable 8: checkcast #9 // class DoubleCast 11: astore_1 12: return LineNumberTable: line 3: 0 line 4: 4 line 5: 12 RuntimeVisibleTypeAnnotations: 0: #15(): CAST, offset=8, type_index=1 Anno Note that the bytecode offset in the attribute points to the CHECKCAST instruction associated with the first cast type (DoubleCheckcast), not the second, annotated type (Runnable), even though the type_index is correctly pointing to the second type (Runnable). I've also seen examples where the two CHECKCAST instructions are emitted in the reverse order; in those cases, the same thing happens, i.e., offset points to the first CHECKCAST to DoubleCheckcast instead of the second CHECKCAST to Runnable. The JLS specifies only that offset refers to "the bytecode instruction corresponding to the cast expression", which is ambiguous because for an intersection cast there are multiple such bytecodes. But even if you tried to read that generously as "the first bytecode instruction corresponding to the cast expression" then the example above would still be incorrect. In any case, as things stand now it seems impossible to correctly identify which type has the annotation: even if you look at the type_index there's no guarantee that the order of the CHECKCAST instructions matches the order in the source code, and even if there were such a guarantee, because the bytecode offset is wrong, you'd be counting from the wrong offset. Behavior confirmed on 17, 25, & 26. Thanks, -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Mon Nov 10 20:38:10 2025 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Mon, 10 Nov 2025 14:38:10 -0600 Subject: Classfile type annotation for INSTANCEOF expressions Message-ID: Consider this class: import java.lang.annotation.*; public class InstancePat { InstancePat(Object o) { if (o instanceof @Anno Runnable) { @Anno Runnable r = (@Anno Runnable)o; System.out.println(r); } } InstancePat(Object o, int x) { if (o instanceof @Anno Runnable r) System.out.println(r); } } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) @interface Anno { } Here's the javap output (edited for brevity): InstancePat(java.lang.Object); 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: aload_1 5: instanceof #7 // class java/lang/Runnable 8: ifeq 23 11: aload_1 12: checkcast #7 // class java/lang/Runnable 15: astore_2 16: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream; 19: aload_2 20: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 23: return RuntimeVisibleTypeAnnotations: 0: #27(): INSTANCEOF, offset=5 Anno 1: #27(): CAST, offset=12, type_index=0 Anno 2: #27(): LOCAL_VARIABLE, {start_pc=16, length=7, index=2} Anno InstancePat(java.lang.Object, int); 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: aload_1 5: instanceof #7 // class java/lang/Runnable 8: ifeq 23 11: aload_1 12: checkcast #7 // class java/lang/Runnable 15: astore_3 16: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream; 19: aload_3 20: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 23: return RuntimeVisibleTypeAnnotations: 0: #27(): LOCAL_VARIABLE, {start_pc=16, length=7, index=3} Anno Note the RuntimeVisibleTypeAnnotations entries for INSTANCEOF and CAST have disappeared in the second constructor. Is this behavior expected? This question is related to my previous one about CAST expressions... both questions ask about "holes" in the story being told by the classfile relating to where type annotations occurred in the original source. Stepping back, what is the actual intent here? I had assumed that, given correct class files, a bytecode analysis tool should be able to "keep track of" every type annotation that existed in the original source code, but maybe I'm reading too much into things (I didn't witness the discussion that led to these classfile attributes). Thanks for any clarifications. -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From acobbs at openjdk.org Mon Nov 10 20:59:08 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 10 Nov 2025 20:59:08 GMT Subject: RFR: 8371162: Compiler warns about implicit cast from long to int in shift operation [v2] In-Reply-To: References: Message-ID: > Consider code like this: > > int x = 1; > x <<= 1L; > > The compiler currently emits this warning: > > warning: [lossy-conversions] implicit cast from long to int in compound assignment is possibly lossy > x <<= 1L; > ^ > > By definition, bit shift operations only use the bottom 5 or 6 bits of the specified shift amount (in this example, `1L`), and the JLS does not require the shift amount to be any specific integral type, only that that it be some integral type. So as long all but the bottom 5 or 6 bits are zero, there is no loss of information and the warning is inappropriate. > > The case where the bottom 5 or 6 bits are _not_ all zero is addressed separately in [JDK-5038439](https://bugs.openjdk.org/browse/JDK-5038439). Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: Use cleaner switch statement syntax. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28180/files - new: https://git.openjdk.org/jdk/pull/28180/files/43c91117..e09ba44f Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28180&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28180&range=00-01 Stats: 6 lines in 1 file changed: 0 ins; 4 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/28180.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28180/head:pull/28180 PR: https://git.openjdk.org/jdk/pull/28180 From acobbs at openjdk.org Mon Nov 10 22:24:52 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 10 Nov 2025 22:24:52 GMT Subject: RFR: 8344159: Add lint warnings for unnecessary warning suppression [v5] In-Reply-To: References: Message-ID: <26Gs2omFeLXWjo85AUbAb34PpolWLLsjB2aMS92fNKY=.04fb0491-212d-4212-9dde-08250f361053@github.com> > This PR adds a new compiler warning for `@SuppressWarnings` annotations that don't actually suppress any warnings. > > Summary of code changes: > > * Add new warning and associated lint category `"suppression"` > * Update `LintMapper` to keep track of which `@SuppressWarnings` suppressions have been validated ? > * Update `Log.warning()` so it validates any current suppression of the warning's lint category in effect. > * Add a new `validate` parameter to `Lint.isEnabled()` and `Lint.isSuppressed()` that specifies whether to also validate any current suppression. > * Add `Lint.isActive()` to check whether a category is enabled _or_ suppression of the category is being tracked - in other words, whether the warning calculation needs to be performed. Used for non-trivial warning calculations. > * Add `-Xlint:-suppression` flags to `*.gmk` build files so the build doesn't break > > ? The suppression of a lint category is "validated" as soon as it suppresses some warning in that category Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 135 commits: - Suppress new unnecessary suppresion warnings created by recent commits. - Merge branch 'master' into JDK-8344159 - Merge branch 'master' into JDK-8344159 to fix conflict. - Merge branch 'master' into JDK-8344159 to fix conflict. - Merge branch 'master' into JDK-8344159 to fix conflicts. - Add clarifying comment. - Merge branch 'master' into JDK-8344159 - Change inner class name to avoid shadowing superclass name. - Add a couple of code clarification comments. - Refactor test to avoid requiring changes to TestRunner. - ... and 125 more: https://git.openjdk.org/jdk/compare/43afce54...aaf029e8 ------------- Changes: https://git.openjdk.org/jdk/pull/25167/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=25167&range=04 Stats: 1667 lines in 35 files changed: 1492 ins; 49 del; 126 mod Patch: https://git.openjdk.org/jdk/pull/25167.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/25167/head:pull/25167 PR: https://git.openjdk.org/jdk/pull/25167 From vromero at openjdk.org Tue Nov 11 02:47:49 2025 From: vromero at openjdk.org (Vicente Romero) Date: Tue, 11 Nov 2025 02:47:49 GMT Subject: RFR: 8369517: Compilation mismatch for equivalent lambda and method reference [v4] In-Reply-To: References: Message-ID: > Given the following test case: > > > import java.util.function.Supplier; > interface Main { > interface X { > X self(); > } > > static X makeX() {return null;} > > static X create(Supplier supplier) {return null;} > > static X> methodRef() { > return create(Main::makeX).self(); > } > > static X> lambda() { > return create(() -> makeX()).self(); > } > } > > > javac reports an error for the method reference but not for the lambda. There should be no difference here (error in both cases) Vicente Romero has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains four additional commits since the last revision: - Merge branch 'master' into JDK-8369517 - updating test - fixing issues - 8369517: Compilation mismatch for equivalent lambda and method reference ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27737/files - new: https://git.openjdk.org/jdk/pull/27737/files/53f7d475..1efd9f87 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27737&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27737&range=02-03 Stats: 270123 lines in 2510 files changed: 172590 ins; 59384 del; 38149 mod Patch: https://git.openjdk.org/jdk/pull/27737.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27737/head:pull/27737 PR: https://git.openjdk.org/jdk/pull/27737 From pminborg at openjdk.org Tue Nov 11 08:01:08 2025 From: pminborg at openjdk.org (Per Minborg) Date: Tue, 11 Nov 2025 08:01:08 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v24] In-Reply-To: References: Message-ID: On Mon, 10 Nov 2025 14:59:03 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Add @AOTSafeClassInitializer As per https://github.com/openjdk/jdk/pull/27605/commits/e479cb4bbe54f3e0caa129cc45aec2ec2bffd9cf, this PR passes tier 1-4 on multiple platforms. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3515424778 From duke at openjdk.org Tue Nov 11 12:43:41 2025 From: duke at openjdk.org (Jesse Glick) Date: Tue, 11 Nov 2025 12:43:41 GMT Subject: RFR: 8173970: jar tool should have a way to extract to a directory [v16] In-Reply-To: References: Message-ID: On Thu, 17 Oct 2024 04:51:53 GMT, Jaikiran Pai wrote: >> Can I please get a review for this patch which proposes to implement the enhancement request noted in https://bugs.openjdk.java.net/browse/JDK-8173970? >> >> Edit: This PR description has now been updated to match the changes that were done over the course of review inputs that were received for this enhancement. >> >> The commit in this PR introduces the ability to use `jar` tool to extract the contents of the JAR file to a specific directory of choice. Optional `-C` and `--dir` options are added to the `-x` main operation of the jar tool. The value for these options is expected to be a file path which is expected to be a directory to which the jar will be extracted. When neither `-C` nor `--dir` are used, the extract operation of the jar tool will continue to behave like it did before this enhancement and will extract the jar into the current working directory. >> >> The commit also includes a jtreg testcase which verifies the usage of this new option. > > Jaikiran Pai has updated the pull request incrementally with one additional commit since the last revision: > > Lance's man page inputs src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties line 264: > 262: \ versions. > 263: main.help.opt.any=\ > 264: \ Operation modifiers valid in any mode:\n\ This text _valid in any mode_ was present in earlier releases but does not seem to have been true for `-C` with `-x`. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/2752#discussion_r2514095868 From jlahoda at openjdk.org Tue Nov 11 12:44:27 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 11 Nov 2025 12:44:27 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v4] In-Reply-To: <7G0o3Ph7D9I11xzojJwIXuJ4nHvNtXtQpy2BdfuZ6Kw=.b1766068-44ad-4a74-ac51-b37b191c3e65@github.com> References: <7G0o3Ph7D9I11xzojJwIXuJ4nHvNtXtQpy2BdfuZ6Kw=.b1766068-44ad-4a74-ac51-b37b191c3e65@github.com> Message-ID: <5mFMpFFAvU3VPLU8lud1zyDDXxdILSys4MoCYoVwiZI=.8fb13cf9-8e20-4aee-9c72-5d2f0fed2ece@github.com> On Thu, 6 Nov 2025 21:03:01 GMT, Archie Cobbs wrote: >> When bit shifting an `int` or `long` value by an amount `X`, all but the last 5 or 6 (respectively) bits of `X` are ignored. >> >> This can create a trap for the unwary, as in this example: >> >> public long readLongBigEndian(byte[] buf, int offset) { >> return ((buf[offset + 0] & 0xff) << 56) // BUG HERE >> | ((buf[offset + 1] & 0xff) << 48) // BUG HERE >> | ((buf[offset + 2] & 0xff) << 40) // BUG HERE >> | ((buf[offset + 3] & 0xff) << 32) // BUG HERE >> | ((buf[offset + 4] & 0xff) << 24) >> | ((buf[offset + 5] & 0xff) << 16) >> | ((buf[offset + 6] & 0xff) << 8) >> | ((buf[offset + 7] & 0xff); >> } >> >> This PR adds a new warning when the compiler detects an out-of-range bit shift, i.e., an `int` bit shift not in the range `[-31...31]` or a `long` bit shift not in the range `[-63...63]`. > > Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: > > Don't warn for negative shift values that are otherwise in range. Looks good to me. I think I prefer this more conservative approach. Thanks! FWIW, from a corpus run, there are 5 cases of shift `-1`, 2 cases of shift `-5` and one cases of shift `-31`. ------------- Marked as reviewed by jlahoda (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27102#pullrequestreview-3447888795 PR Comment: https://git.openjdk.org/jdk/pull/27102#issuecomment-3516714885 From jlahoda at openjdk.org Tue Nov 11 13:56:09 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 11 Nov 2025 13:56:09 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v8] In-Reply-To: References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Message-ID: On Sun, 9 Nov 2025 18:30:53 GMT, Liam Miller-Cushon wrote: >> Hi, please consider this fix for [JDK-8370800: Downgrade cant.attach.type.annotations diagnostics to warnings](https://bugs.openjdk.org/browse/JDK-8370800). >> >> As discussed in the, this reduces the compatibility impact of these diagnostics for builds that deliberately omit transitive annotation dependencies, for example if they are only referenced through javadoc `@link` tags, or by frameworks that conditionally load the classes. >> >> The PR changes the existing error diagnostic to an unconditional warning. Another alternative would be to make it an optional xlint diagnostic, perhaps as part of `-Xlint:classfile`, or as another category. > > Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: > > Complete symbols returned by getAllMembers I was looking into this a bit more. I am afraid I don't see any really good solution. So, out of the not-so-good solutions, the original solution seems least problematic. (With the `DeferredCompletionFailureHandler`, of course, we can't ignore the `CompletionFailure`s completely.) I suspect this probably should be documented in a CSR. @jddarcy, what do you think? Sorry for the fuss. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28018#issuecomment-3517036952 From cushon at openjdk.org Tue Nov 11 14:05:17 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Tue, 11 Nov 2025 14:05:17 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v8] In-Reply-To: References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Message-ID: On Sun, 9 Nov 2025 18:30:53 GMT, Liam Miller-Cushon wrote: >> Hi, please consider this fix for [JDK-8370800: Downgrade cant.attach.type.annotations diagnostics to warnings](https://bugs.openjdk.org/browse/JDK-8370800). >> >> As discussed in the, this reduces the compatibility impact of these diagnostics for builds that deliberately omit transitive annotation dependencies, for example if they are only referenced through javadoc `@link` tags, or by frameworks that conditionally load the classes. >> >> The PR changes the existing error diagnostic to an unconditional warning. Another alternative would be to make it an optional xlint diagnostic, perhaps as part of `-Xlint:classfile`, or as another category. > > Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: > > Complete symbols returned by getAllMembers Thanks for taking another look, and I'm happy to write up a CSR. (If we go with a warning I would like to consider putting it in an `-Xlint` category, that detail could be discussed in the CSR if you're open to considering that.) I'm curious if you'd be willing to share your thoughts on the alternative of lazily attaching the type annotations in `MethodSymbol#complete`, though? I think in theory I prefer that behaviour. In practice it seems like `complete` is only intended to be used for `ClassSymbol`, so using it for `MethodSymbol` is maybe a significant departure from that and would require 'hardening' `MethodSymbol` to ensure that it actually calls complete in all of the methods that would allow accessing type annotation information. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28018#issuecomment-3517075889 From jlahoda at openjdk.org Tue Nov 11 15:05:50 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 11 Nov 2025 15:05:50 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v8] In-Reply-To: References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Message-ID: On Sun, 9 Nov 2025 18:30:53 GMT, Liam Miller-Cushon wrote: >> Hi, please consider this fix for [JDK-8370800: Downgrade cant.attach.type.annotations diagnostics to warnings](https://bugs.openjdk.org/browse/JDK-8370800). >> >> As discussed in the, this reduces the compatibility impact of these diagnostics for builds that deliberately omit transitive annotation dependencies, for example if they are only referenced through javadoc `@link` tags, or by frameworks that conditionally load the classes. >> >> The PR changes the existing error diagnostic to an unconditional warning. Another alternative would be to make it an optional xlint diagnostic, perhaps as part of `-Xlint:classfile`, or as another category. > > Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: > > Complete symbols returned by getAllMembers If it was only for methods (and possibly fields), then using the completers might work at this time, as we don't use completers on those for anything else (I think!). If we ever wanted to use the completers on methods/fields for anything else, then might get into a hard-to-solve state. (Overall, using completers and very carefully calling complete at specific times but not otherwise to avoid errors feels a bit subtle - the current behavior of completers is already pretty complex.) For classes, completing is done often and at "arbitrary" points in time - we could not use the same trick there. And I am not sure if we could attach TAs on classes eagerly. E.g. enhancing your test with: class B> { .. would lead to a failure, while having: class B> { ... would not, I think. I was thinking if we could attach the TAs without completing the types (which would allow us to keep the same behavior that is present without the TAs), but I didn't see a reasonable way to do that. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28018#issuecomment-3517334189 From cushon at openjdk.org Tue Nov 11 15:28:48 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Tue, 11 Nov 2025 15:28:48 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v8] In-Reply-To: References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Message-ID: On Tue, 11 Nov 2025 15:03:19 GMT, Jan Lahoda wrote: > I am not sure if we could attach TAs on classes eagerly. The feedback I've heard about these diagnostics has been for the field/method cases. I understand the use-case is something like the example below, where in practice the issues that have come up are all with method (and maybe fields), but not classes. I think eagerly attaching TAs to classes and only lazily attaching TAs for methods/fields would address the complaints. // Api is packaged in a jar that does not include Foo or Bar, clients optionally bring their own implementations of those classes class Api { static void foo(Foo foo) {...{ static void bar(Bar foo) {...{ } } // Client depends on a jar provided API, and a jar providing Foo. Bar is not on the classpath. class Client { void (Api api, Foo foo) { api.foo(foo); } } ------------- PR Comment: https://git.openjdk.org/jdk/pull/28018#issuecomment-3517446178 From acobbs at openjdk.org Tue Nov 11 16:21:27 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Tue, 11 Nov 2025 16:21:27 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v4] In-Reply-To: <5mFMpFFAvU3VPLU8lud1zyDDXxdILSys4MoCYoVwiZI=.8fb13cf9-8e20-4aee-9c72-5d2f0fed2ece@github.com> References: <7G0o3Ph7D9I11xzojJwIXuJ4nHvNtXtQpy2BdfuZ6Kw=.b1766068-44ad-4a74-ac51-b37b191c3e65@github.com> <5mFMpFFAvU3VPLU8lud1zyDDXxdILSys4MoCYoVwiZI=.8fb13cf9-8e20-4aee-9c72-5d2f0fed2ece@github.com> Message-ID: On Tue, 11 Nov 2025 12:41:15 GMT, Jan Lahoda wrote: > Looks good to me. I think I prefer this more conservative approach. Thanks! I am also convinced now the more conservative approach is better. Thanks for your reviews and helping nail down the best approach. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27102#issuecomment-3517690967 From cstein at openjdk.org Tue Nov 11 18:45:48 2025 From: cstein at openjdk.org (Christian Stein) Date: Tue, 11 Nov 2025 18:45:48 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file [v2] In-Reply-To: References: Message-ID: > Please review this change to include a validation check for expecting an optional JAR manifest entry being the first or second entry in JAR file. As the second entry, it must be only preceeded by an entry for the `META-INF/` directory. Christian Stein has updated the pull request incrementally with one additional commit since the last revision: Split test steps ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28154/files - new: https://git.openjdk.org/jdk/pull/28154/files/2af59381..28068ea6 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28154&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28154&range=00-01 Stats: 12 lines in 1 file changed: 6 ins; 6 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/28154.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28154/head:pull/28154 PR: https://git.openjdk.org/jdk/pull/28154 From cstein at openjdk.org Tue Nov 11 18:51:02 2025 From: cstein at openjdk.org (Christian Stein) Date: Tue, 11 Nov 2025 18:51:02 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file [v2] In-Reply-To: <0kXR9LUYkpot1AJkkAk659sl0To-INwK5nOwR9wxozI=.9c076fb1-04d9-4e54-89ef-28c48c30f3b1@github.com> References: <0kXR9LUYkpot1AJkkAk659sl0To-INwK5nOwR9wxozI=.9c076fb1-04d9-4e54-89ef-28c48c30f3b1@github.com> Message-ID: On Mon, 10 Nov 2025 13:55:33 GMT, Jorn Vernee wrote: >> Christian Stein has updated the pull request incrementally with one additional commit since the last revision: >> >> Split test steps > > test/jdk/tools/jar/ValidatorTest.java line 354: > >> 352: jar("--validate --file " + path); >> 353: fail("Expecting non-zero exit code validating: " + path); >> 354: } catch (IOException e) { > > It's just that `jar` method that throws the expected exception, right? Could you limit the length of the `try` block to not cover the nested try block? Otherwise, if `JarInputStream` starts throwing the same exception, this test would stop testing the `jar` method. (also I think it makes it a little clearer which line is expected to throw) Applied in https://github.com/openjdk/jdk/pull/28154/commits/28068ea6bf7b95fa6427cf644102ba3df9c3fa32 ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28154#discussion_r2515301732 From lancea at openjdk.org Tue Nov 11 19:01:03 2025 From: lancea at openjdk.org (Lance Andersen) Date: Tue, 11 Nov 2025 19:01:03 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file [v2] In-Reply-To: References: Message-ID: On Tue, 11 Nov 2025 18:45:48 GMT, Christian Stein wrote: >> Please review this change to include a validation check for expecting an optional JAR manifest entry being the first or second entry in JAR file. As the second entry, it must be only preceeded by an entry for the `META-INF/` directory. > > Christian Stein has updated the pull request incrementally with one additional commit since the last revision: > > Split test steps src/jdk.jartool/share/classes/sun/tools/jar/Validator.java line 257: > 255: errorAndInvalid(formatMsg("error.validator.wrong.position", firstName, "0")); > 256: } > 257: } I would suggest to move this check to after the order mismatch validation below as the checks also validate if the manifest is missing in the LOC or CEN or out of order By doing so you will also guarantee that Manifest is at the same offset it both he LOC and CEN ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28154#discussion_r2511473421 From cstein at openjdk.org Tue Nov 11 19:09:38 2025 From: cstein at openjdk.org (Christian Stein) Date: Tue, 11 Nov 2025 19:09:38 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file [v3] In-Reply-To: References: Message-ID: <40najGNF67k5YUI2jmSPDijNRRSfdCwPCAfGwmivqFU=.3dd7e106-2452-4b0b-906e-63fa22377030@github.com> > Please review this change to include a validation check for expecting an optional JAR manifest entry being the first or second entry in JAR file. As the second entry, it must be only preceeded by an entry for the `META-INF/` directory. Christian Stein has updated the pull request incrementally with one additional commit since the last revision: Move manifest location check to after the order mismatch validation ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28154/files - new: https://git.openjdk.org/jdk/pull/28154/files/28068ea6..9986cd87 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28154&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28154&range=01-02 Stats: 25 lines in 1 file changed: 13 ins; 12 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/28154.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28154/head:pull/28154 PR: https://git.openjdk.org/jdk/pull/28154 From cstein at openjdk.org Tue Nov 11 19:09:40 2025 From: cstein at openjdk.org (Christian Stein) Date: Tue, 11 Nov 2025 19:09:40 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file [v3] In-Reply-To: References: Message-ID: On Mon, 10 Nov 2025 17:58:25 GMT, Lance Andersen wrote: >> Christian Stein has updated the pull request incrementally with one additional commit since the last revision: >> >> Move manifest location check to after the order mismatch validation > > src/jdk.jartool/share/classes/sun/tools/jar/Validator.java line 257: > >> 255: errorAndInvalid(formatMsg("error.validator.wrong.position", firstName, "0")); >> 256: } >> 257: } > > I would suggest to move this check to after the order mismatch validation below as the checks also validate if the manifest is missing in the LOC or CEN or out of order > > By doing so you will also guarantee that Manifest is at the same offset it both he LOC and CEN Applied by https://github.com/openjdk/jdk/commit/9986cd87d732ed899d9a6300951f6e65d6a12eeb ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28154#discussion_r2515365378 From lancea at openjdk.org Tue Nov 11 19:21:03 2025 From: lancea at openjdk.org (Lance Andersen) Date: Tue, 11 Nov 2025 19:21:03 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file [v3] In-Reply-To: <40najGNF67k5YUI2jmSPDijNRRSfdCwPCAfGwmivqFU=.3dd7e106-2452-4b0b-906e-63fa22377030@github.com> References: <40najGNF67k5YUI2jmSPDijNRRSfdCwPCAfGwmivqFU=.3dd7e106-2452-4b0b-906e-63fa22377030@github.com> Message-ID: On Tue, 11 Nov 2025 19:09:38 GMT, Christian Stein wrote: >> Please review this change to include a validation check for expecting an optional JAR manifest entry being the first or second entry in JAR file. As the second entry, it must be only preceeded by an entry for the `META-INF/` directory. > > Christian Stein has updated the pull request incrementally with one additional commit since the last revision: > > Move manifest location check to after the order mismatch validation test/jdk/tools/jar/ValidatorTest.java line 342: > 340: } > 341: > 342: private void testWrongManifestPosition( This new test only validates that the LOC MANIFEST.MF entries are where they need to be. It does not do a similar CEN check in the event that the LOC and CEN entries do not match. If you change your validation order so that Validator checks the MANIFEST location after it checks the order, then you should be covered. I would also add a comment to the test to help future maintainers to the test ... ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28154#discussion_r2515410239 From cstein at openjdk.org Wed Nov 12 07:09:03 2025 From: cstein at openjdk.org (Christian Stein) Date: Wed, 12 Nov 2025 07:09:03 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file [v3] In-Reply-To: References: <40najGNF67k5YUI2jmSPDijNRRSfdCwPCAfGwmivqFU=.3dd7e106-2452-4b0b-906e-63fa22377030@github.com> Message-ID: <5SVrnXXcVGQgTledYjujDGtcfsUccxoJH0ba1bUkzFA=.adfbbc3b-d779-4386-80cb-46d7055132f9@github.com> On Tue, 11 Nov 2025 19:18:35 GMT, Lance Andersen wrote: >> Christian Stein has updated the pull request incrementally with one additional commit since the last revision: >> >> Move manifest location check to after the order mismatch validation > > test/jdk/tools/jar/ValidatorTest.java line 342: > >> 340: } >> 341: >> 342: private void testWrongManifestPosition( > > This new test only validates that the LOC MANIFEST.MF entries are where they need to be. It does not do a similar CEN check in the event that the LOC and CEN entries do not match. > > If you change your validation order so that Validator checks the MANIFEST location after it checks the order, then you should be covered. > > I would also add a comment to the test to help future maintainers to the test ... I'll add such a comment. The existing tests for LOC-CEN related mismatches should already cover those cases. In addition, the results of the checks in `Validator` are accumulated - so their order is not important, right? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28154#discussion_r2517154697 From jlahoda at openjdk.org Wed Nov 12 07:18:15 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 12 Nov 2025 07:18:15 GMT Subject: Integrated: 8366691: JShell should support a more convenient completion In-Reply-To: References: Message-ID: On Tue, 2 Sep 2025 13:05:01 GMT, Jan Lahoda wrote: > JShell tool has the code completion feature in the terminal, allowing to tab-complete inputs. The JShell engine also has an API to compute the completions. But, the API is more suitable for a terminal-based UI, not for a GUI. > > The goal in this PR is to provide an API that would allow better code completions in GUI frontends for JShell. > > The main idea here is that the user of the API will get information could the context and `Element` that can continue the current input, and can produce UI elements/strings out of this information as necessary. > > The apidiff for the current API is available here: > https://cr.openjdk.org/~jlahoda/8366691/JDK-8366691.00/ This pull request has now been integrated. Changeset: 76a0732b Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/76a0732ba5c0f3159ed0ebc5fcb2dfb7117b38cd Stats: 954 lines in 8 files changed: 792 ins; 73 del; 89 mod 8366691: JShell should support a more convenient completion Reviewed-by: asotona ------------- PR: https://git.openjdk.org/jdk/pull/27049 From cstein at openjdk.org Wed Nov 12 07:20:44 2025 From: cstein at openjdk.org (Christian Stein) Date: Wed, 12 Nov 2025 07:20:44 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file [v4] In-Reply-To: References: Message-ID: > Please review this change to include a validation check for expecting an optional JAR manifest entry being the first or second entry in JAR file. As the second entry, it must be only preceeded by an entry for the `META-INF/` directory. Christian Stein has updated the pull request incrementally with one additional commit since the last revision: Add comment to test ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28154/files - new: https://git.openjdk.org/jdk/pull/28154/files/9986cd87..b7389cb6 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28154&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28154&range=02-03 Stats: 9 lines in 1 file changed: 6 ins; 0 del; 3 mod Patch: https://git.openjdk.org/jdk/pull/28154.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28154/head:pull/28154 PR: https://git.openjdk.org/jdk/pull/28154 From amaembo at gmail.com Wed Nov 12 07:48:05 2025 From: amaembo at gmail.com (Tagir Valeev) Date: Wed, 12 Nov 2025 08:48:05 +0100 Subject: Type-use annotation on var lambda parameter In-Reply-To: References: Message-ID: Hello again! Thanks to Srikanth Sankaran from the Eclipse compiler project, I've got an additional context about this problem. Between Java 11 and Java 19, the specification was saying a slightly different thing [1]: > If the annotation appears before a void method declaration or a local variable declaration that uses var (?14.4), then there is no closest type. Since Java 20, it was changed: > If the annotation appears before a void method declaration or a variable declaration that uses var (?14.4, ?15.27.1), then there is no closest type. This specification problem was reported as JDK-8295807 by Dan Smith [3] and fixed by Gavin Bierman, as the result of the earlier report by Chris Povirk [4]. However, it looks like the javac implementation was never updated to reflect this specification change. I've created an issue JDK-8371683 in tools/javac [5]. With best regards, Tagir Valeev [1] https://docs.oracle.com/javase/specs/jls/se19/html/jls-9.html#jls-9.7.4 [2] https://docs.oracle.com/javase/specs/jls/se20/html/jls-9.html#jls-9.7.4 [3] https://bugs.openjdk.org/browse/JDK-8295807 [4] https://mail.openjdk.org/pipermail/compiler-dev/2022-October/020593.html [5] https://bugs.openjdk.org/browse/JDK-8371683 On Mon, Nov 3, 2025 at 12:32?PM Tagir Valeev wrote: > Hello! > > I stumbled on the following issue. Let's consider this Java file: > > package com.example; > > import java.lang.annotation.Retention; > import java.lang.annotation.Target; > import java.util.function.Function; > > import static java.lang.annotation.ElementType.TYPE_USE; > import static java.lang.annotation.RetentionPolicy.RUNTIME; > > @Retention(value=RUNTIME) > @Target(value={TYPE_USE}) > @interface Anno { > } > public class TestClass { > public static void main(String[] args) { > Function f = (@Anno var val ) -> > Integer.toHexString(val); > System.out.println(f.apply(10)); > } > } > > As you can see, there's a TYPE_USE annotation which is applied to the > lambda parameter declared with 'var' keyword. If I understand JLS 9.7.4 [1] > correctly, this should not be legal: > > > If the annotation appears before a void method declaration or a variable > declaration that uses var (?14.4, ?15.27.1), then there is no closest type. > If the annotation's interface is deemed to apply only to the type which is > closest to the annotation, a compile-time error occurs. > > However, javac accepts this code. I tried different versions between Java > 11 and Java 25, and the result is the same: the file is compiled > successfully. However, the TestClass.class file contains no references to > the Anno annotation at all, despite it having the RUNTIME retention. So it > looks like the annotation is silently ignored. > > One thing that confuses me is that the Eclipse compiler (ecj-4.34.jar) > also accepts this code. However, it generates > a RuntimeVisibleTypeAnnotations attribute for the Anno annotation. So > either both compilers accept this code incorrectly, or my understanding of > the specification is wrong. > > Could you please take a look at the javac issue? I'd be happy to be > corrected if I misunderstood the specification. Thank you in advance! > > Tagir Valeev > > [1] > https://docs.oracle.com/javase/specs/jls/se25/html/jls-9.html#jls-9.7.4 > -------------- next part -------------- An HTML attachment was scrubbed... URL: From alanb at openjdk.org Wed Nov 12 08:14:26 2025 From: alanb at openjdk.org (Alan Bateman) Date: Wed, 12 Nov 2025 08:14:26 GMT Subject: RFR: 8173970: jar tool should have a way to extract to a directory [v16] In-Reply-To: References: Message-ID: On Tue, 11 Nov 2025 12:40:29 GMT, Jesse Glick wrote: >> Jaikiran Pai has updated the pull request incrementally with one additional commit since the last revision: >> >> Lance's man page inputs > > src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties line 264: > >> 262: \ versions. >> 263: main.help.opt.any=\ >> 264: \ Operation modifiers valid in any mode:\n\ > > This text _valid in any mode_ was present in earlier releases but does not seem to have been true for `-C` with `-x`. Do we need to create a bug to check the help output? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/2752#discussion_r2517325560 From pminborg at openjdk.org Wed Nov 12 10:07:39 2025 From: pminborg at openjdk.org (Per Minborg) Date: Wed, 12 Nov 2025 10:07:39 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v25] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 112 commits: - Clarify toString spec - Merge branch 'master' into lazy-constants - Add @AOTSafeClassInitializer - Address comments in PR - Fix merge mistake - Merge master - Rework toString implementations - Update after doc comments - Merge branch 'master' into lazy-constants - Revert the AbstractMap.keySet @Stable annotation - ... and 102 more: https://git.openjdk.org/jdk/compare/76a1109d...1f439bec ------------- Changes: https://git.openjdk.org/jdk/pull/27605/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=24 Stats: 8445 lines in 60 files changed: 3836 ins; 4490 del; 119 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From jvernee at openjdk.org Wed Nov 12 12:18:04 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Wed, 12 Nov 2025 12:18:04 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file [v4] In-Reply-To: References: Message-ID: <647L2WUdlyyz_lCer-cWGhypEEjtv5CO5pFtpRwga3o=.13596e36-16dc-4688-bd11-b01d95ee5529@github.com> On Wed, 12 Nov 2025 07:20:44 GMT, Christian Stein wrote: >> Please review this change to include a validation check for expecting an optional JAR manifest entry being the first or second entry in JAR file. As the second entry, it must be only preceeded by an entry for the `META-INF/` directory. > > Christian Stein has updated the pull request incrementally with one additional commit since the last revision: > > Add comment to test Marked as reviewed by jvernee (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/28154#pullrequestreview-3453142623 From vromero at openjdk.org Wed Nov 12 14:33:46 2025 From: vromero at openjdk.org (Vicente Romero) Date: Wed, 12 Nov 2025 14:33:46 GMT Subject: Integrated: 8369517: Compilation mismatch for equivalent lambda and method reference In-Reply-To: References: Message-ID: On Thu, 9 Oct 2025 19:26:36 GMT, Vicente Romero wrote: > Given the following test case: > > > import java.util.function.Supplier; > interface Main { > interface X { > X self(); > } > > static X makeX() {return null;} > > static X create(Supplier supplier) {return null;} > > static X> methodRef() { > return create(Main::makeX).self(); > } > > static X> lambda() { > return create(() -> makeX()).self(); > } > } > > > javac reports an error for the method reference but not for the lambda. There should be no difference here (error in both cases) This pull request has now been integrated. Changeset: e5a272a5 Author: Vicente Romero URL: https://git.openjdk.org/jdk/commit/e5a272a59058e36136acd6aef635f87136fbb027 Stats: 58 lines in 4 files changed: 56 ins; 0 del; 2 mod 8369517: Compilation mismatch for equivalent lambda and method reference Reviewed-by: mcimadamore ------------- PR: https://git.openjdk.org/jdk/pull/27737 From duke at openjdk.org Wed Nov 12 15:02:12 2025 From: duke at openjdk.org (Jesse Glick) Date: Wed, 12 Nov 2025 15:02:12 GMT Subject: RFR: 8173970: jar tool should have a way to extract to a directory [v16] In-Reply-To: References: Message-ID: On Wed, 12 Nov 2025 08:11:52 GMT, Alan Bateman wrote: >> src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties line 264: >> >>> 262: \ versions. >>> 263: main.help.opt.any=\ >>> 264: \ Operation modifiers valid in any mode:\n\ >> >> This text _valid in any mode_ was present in earlier releases but does not seem to have been true for `-C` with `-x`. > > Do we need to create a bug to check the help output? Does not seem worth a backport, just noting this for the record. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/2752#discussion_r2518654756 From lancea at openjdk.org Wed Nov 12 15:16:40 2025 From: lancea at openjdk.org (Lance Andersen) Date: Wed, 12 Nov 2025 15:16:40 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file [v4] In-Reply-To: References: Message-ID: On Wed, 12 Nov 2025 07:20:44 GMT, Christian Stein wrote: >> Please review this change to include a validation check for expecting an optional JAR manifest entry being the first or second entry in JAR file. As the second entry, it must be only preceeded by an entry for the `META-INF/` directory. > > Christian Stein has updated the pull request incrementally with one additional commit since the last revision: > > Add comment to test Thank you for moving the Manifest position checking as it helps improve the overall validation checking WRT the new Resource: error.validator.wrong.position, I believe this is only used by your new check and if so, perhaps consider making the message more specific indicating the Manifest was not found in either entry 1 or 2 (or something like that) a couple of other responses below but all good test/jdk/tools/jar/ValidatorTest.java line 315: > 313: /** > 314: * Validates that the LOC MANIFEST.MF entries are at the expected positions. > 315: * Thank you for adding a comment. I might suggest adding a little more clarity or point to JarInputStream docs as the Manifest Location for JarFile is not an issue. The issue boils down to the fact that JarInputStream walks the LOC sequentially and because of this there is the limitation on the location of where the Manifest can live. Not a big deal overall and I will leave it to you. It is just no obvious to someone who is working in this area the 1st time as this issue is not directly related to the Zip specification, but is a JarInputStream limitation ------------- Marked as reviewed by lancea (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28154#pullrequestreview-3453879848 PR Review Comment: https://git.openjdk.org/jdk/pull/28154#discussion_r2518637541 From lancea at openjdk.org Wed Nov 12 15:16:45 2025 From: lancea at openjdk.org (Lance Andersen) Date: Wed, 12 Nov 2025 15:16:45 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file [v3] In-Reply-To: <5SVrnXXcVGQgTledYjujDGtcfsUccxoJH0ba1bUkzFA=.adfbbc3b-d779-4386-80cb-46d7055132f9@github.com> References: <40najGNF67k5YUI2jmSPDijNRRSfdCwPCAfGwmivqFU=.3dd7e106-2452-4b0b-906e-63fa22377030@github.com> <5SVrnXXcVGQgTledYjujDGtcfsUccxoJH0ba1bUkzFA=.adfbbc3b-d779-4386-80cb-46d7055132f9@github.com> Message-ID: On Wed, 12 Nov 2025 07:06:21 GMT, Christian Stein wrote: >> test/jdk/tools/jar/ValidatorTest.java line 342: >> >>> 340: } >>> 341: >>> 342: private void testWrongManifestPosition( >> >> This new test only validates that the LOC MANIFEST.MF entries are where they need to be. It does not do a similar CEN check in the event that the LOC and CEN entries do not match. >> >> If you change your validation order so that Validator checks the MANIFEST location after it checks the order, then you should be covered. >> >> I would also add a comment to the test to help future maintainers to the test ... > > I'll add such a comment. > > The existing tests for LOC-CEN related mismatches should already cover those cases. In addition, the results of the checks in `Validator` are accumulated - so their order is not important, right? With moving the location check for the Manifest in Validator to be the last check, we are in good shape Would it have been nice to do the same type of check using the CEN(via JarFile::stream or JarFile::entries)? Sure, but not a must ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28154#discussion_r2518683457 From jvernee at openjdk.org Wed Nov 12 16:39:57 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Wed, 12 Nov 2025 16:39:57 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v25] In-Reply-To: References: Message-ID: On Wed, 12 Nov 2025 10:07:39 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 112 commits: > > - Clarify toString spec > - Merge branch 'master' into lazy-constants > - Add @AOTSafeClassInitializer > - Address comments in PR > - Fix merge mistake > - Merge master > - Rework toString implementations > - Update after doc comments > - Merge branch 'master' into lazy-constants > - Revert the AbstractMap.keySet @Stable annotation > - ... and 102 more: https://git.openjdk.org/jdk/compare/76a1109d...1f439bec Some initial comments on the spec and implementation. I still need to look at the tests. src/java.base/share/classes/java/lang/LazyConstant.java line 48: > 46: * (provided at construction) will be invoked and the result will be used to initialize > 47: * the constant. Once a lazy constant is initialized, its contents can never change > 48: * and will be retrieved over and over again upon subsequent {@linkplain #get() get} Are the above links to `#get()` also intended to have a the plain `get` text? src/java.base/share/classes/java/lang/LazyConstant.java line 169: > 167: * a lazy constant {@linkplain java.lang.ref##reachability strongly references} > 168: * it contents. Hence, a lazy constant will hold its contents until > 169: * the lazy constant itself is collected (if ever). Maybe you could avoid the word 'collected' here, as there are no other references to the GC in this section, and no link to what GC is/does. i.e. I think 'collected' is not well-defined enough to be used here. Suggestion: * it contents. Hence, the contents of a lazy constant will be reachable as long * as the lazy constant itself is reachable. src/java.base/share/classes/java/lang/LazyConstant.java line 249: > 247: > 248: /** > 249: * {@return the {@linkplain System#identityHashCode(Object)} for this lazy constant} How does this link render? It doesn't have any plain text. Maybe it's missing? Suggestion: * {@return the {@linkplain System#identityHashCode(Object) identity hash code} for this lazy constant} src/java.base/share/classes/java/lang/LazyConstant.java line 257: > 255: > 256: /** > 257: * {@return a non-initializing string suitable for debugging} What is a 'non-initializing string'? ;) I think the second paragraph already covers this aspect, so you can leave it out here. src/java.base/share/classes/java/lang/LazyConstant.java line 275: > 273: /** > 274: * {@return a lazy constant to be computed later via the provided > 275: * {@code computingFunction}} The function computes the contents, not the LC itself, so: Suggestion: * {@return a lazy constant whose contents is to be computed later via the provided * {@code computingFunction}} src/java.base/share/classes/java/util/LazyCollections.java line 55: > 53: > 54: // Unsafe allows LazyCollection classes to be used early in the boot sequence > 55: static final Unsafe UNSAFE = Unsafe.getUnsafe(); Suggestion: private static final Unsafe UNSAFE = Unsafe.getUnsafe(); src/java.base/share/classes/java/util/LazyCollections.java line 66: > 64: // using `elements.length`. > 65: @Stable > 66: private final int size; Is this really that important? What about the extra footprint added by the `int` field? We might have many instances of this class, but only one copy of the bytecode. src/java.base/share/classes/java/util/LazyCollections.java line 199: > 197: final int size = base.size(); > 198: subListRangeCheck(fromIndex, toIndex, size); > 199: return new ReverseOrderLazyListView<>(base.subList(size - toIndex, size - fromIndex)); Why not this? (maybe add a comment?) Suggestion: return new ReverseOrderLazyListView<>(base.subList(fromIndex, toIndex)); src/java.base/share/classes/java/util/LazyCollections.java line 264: > 262: > 263: @Stable > 264: private final Map indexMapper; This index mapper is a clever solution that avoids implementing a hashing function again. Lookups through this map can be folded because it is created using `Map.ofEntries`. I think you should put that in a comment here as well. src/java.base/share/classes/java/util/LazyCollections.java line 433: > 431: @Override public V getValue() { > 432: final int index = map.indexFor(getKey); > 433: final V v = map.getAcquire(getKey); I suppose you could use `orElseCompute` here, since you already have the index src/java.base/share/classes/java/util/LazyCollections.java line 488: > 486: static final class Mutexes { > 487: > 488: static final Object TOMB_STONE = new Object(); Suggestion: private static final Object TOMB_STONE = new Object(); src/java.base/share/classes/java/util/LazyCollections.java line 578: > 576: if (t == null) { > 577: final T newValue = switch (functionHolder.function()) { > 578: case Supplier sup -> (T) sup.get(); Is the held function ever a Supplier? I don't see a FunctionHolder being created with one. src/java.base/share/classes/java/util/LazyCollections.java line 607: > 605: assert Thread.holdsLock(mutex) : index + "didn't hold " + mutex; > 606: // We know we hold the monitor here so plain semantic is enough > 607: if (array[index] == null) { This should always be true when we get here, right? src/java.base/share/classes/java/util/List.java line 1222: > 1220: *

> 1221: * Any {@link List#subList(int, int) subList()} or {@link List#reversed()} views > 1222: * of the returned list are also lazily computed. Is this really about the views itself? Or about the elements? (AFAIK these views are typically lazily computed/created for others List impls as well) Suggestion: * The elements of any {@link List#subList(int, int) subList()} or {@link List#reversed()} views * of the returned list are also lazily computed. src/java.base/share/classes/java/util/Map.java line 1765: > 1763: * at most once per key, even in a multi-threaded environment. Competing > 1764: * threads accessing a value already under computation will block until an element > 1765: * is computed or an exception is thrown by the computing thread. I think technically it's more correct to say something like '... or the computing function completes abnormally'. Since, if an exception is throw inside the computing function (by the computing thread), it may be caught and handled inside the computing function as well. src/java.base/share/classes/java/util/Map.java line 1778: > 1776: *

> 1777: * Any {@link Map#values()} or {@link Map#entrySet()} views of the returned map are > 1778: * also lazily computed. Suggestion: * The values of any {@link Map#values()} or {@link Map#entrySet()} views of the returned map are * also lazily computed. src/java.base/share/classes/java/util/Map.java line 1817: > 1815: final Set keyCopies = Set.copyOf(keys); > 1816: Objects.requireNonNull(computingFunction); > 1817: if (keys instanceof EnumSet && !keys.isEmpty()) { The fact that `keys` is being used here and not `keyCopies` looks a bit fishy. In general we should use the validated copy of our data in subsequent processing. Since `EnumSet` is mutable, it seems that these two could go out of sync. ------------- PR Review: https://git.openjdk.org/jdk/pull/27605#pullrequestreview-3448944313 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518699095 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518745565 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518765422 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518768972 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518779499 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518885149 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518897461 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518919343 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518968294 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518950708 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518970767 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2519007486 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2519002745 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518813240 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518832566 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518837814 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518880555 From jvernee at openjdk.org Wed Nov 12 16:39:58 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Wed, 12 Nov 2025 16:39:58 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v25] In-Reply-To: References: Message-ID: On Wed, 12 Nov 2025 15:23:25 GMT, Jorn Vernee wrote: >> Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 112 commits: >> >> - Clarify toString spec >> - Merge branch 'master' into lazy-constants >> - Add @AOTSafeClassInitializer >> - Address comments in PR >> - Fix merge mistake >> - Merge master >> - Rework toString implementations >> - Update after doc comments >> - Merge branch 'master' into lazy-constants >> - Revert the AbstractMap.keySet @Stable annotation >> - ... and 102 more: https://git.openjdk.org/jdk/compare/76a1109d...1f439bec > > src/java.base/share/classes/java/lang/LazyConstant.java line 169: > >> 167: * a lazy constant {@linkplain java.lang.ref##reachability strongly references} >> 168: * it contents. Hence, a lazy constant will hold its contents until >> 169: * the lazy constant itself is collected (if ever). > > Maybe you could avoid the word 'collected' here, as there are no other references to the GC in this section, and no link to what GC is/does. i.e. I think 'collected' is not well-defined enough to be used here. > > Suggestion: > > * it contents. Hence, the contents of a lazy constant will be reachable as long > * as the lazy constant itself is reachable. Alternatively you could say something like 'becomes eligible for garbage collection', but I think defining the spec in terms of reachability is better, since that has a better definition in `java.lang.ref##reachability`. > src/java.base/share/classes/java/util/Map.java line 1765: > >> 1763: * at most once per key, even in a multi-threaded environment. Competing >> 1764: * threads accessing a value already under computation will block until an element >> 1765: * is computed or an exception is thrown by the computing thread. > > I think technically it's more correct to say something like '... or the computing function completes abnormally'. Since, if an exception is throw inside the computing function (by the computing thread), it may be caught and handled inside the computing function as well. (Same for List) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518789003 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518834700 From jvernee at openjdk.org Wed Nov 12 16:39:59 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Wed, 12 Nov 2025 16:39:59 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v25] In-Reply-To: References: <-lErHk2PzyJCaPQGrEwCt3nObTrTHs7_p53eBXspUGE=.50dc2375-8769-49a5-9308-ab40132bbd19@github.com> Message-ID: On Mon, 13 Oct 2025 11:25:04 GMT, Per Minborg wrote: >> Usually a null sentinel is used when null indicates something different. I think maybe to allow folding the empty case, we should probably add a new annotation or a new element-value to indicate this status and properly handle it in C1/C2 (similar to the field trusting in ciField) > > I've added two new benchmarks: > > > private static final LazyConstant> OPTIONAL_42 = LazyConstant.of(() -> Optional.of(42)); > private static final LazyConstant> OPTIONAL_42_2 = LazyConstant.of(() -> Optional.of(42)); > private static final LazyConstant> OPTIONAL_EMPTY = LazyConstant.of(Optional::empty); > private static final LazyConstant> OPTIONAL_EMPTY2 = LazyConstant.of(Optional::empty); > > ... > > @Benchmark > public int staticOptional42() { > return OPTIONAL_42.get().orElseThrow() + OPTIONAL_42_2.get().orElseThrow(); > } > > @Benchmark > public boolean staticOptionalEmpty() { > return OPTIONAL_EMPTY.get().isEmpty() ^ OPTIONAL_EMPTY2.get().isEmpty(); > } > > > > > Which gives: > > > Benchmark Mode Cnt Score Error Units > StableValueBenchmark.staticOptional42 avgt 10 0.354 ? 0.045 ns/op > > Benchmark Mode Cnt Score Error Units > StableValueBenchmark.staticOptionalEmpty avgt 10 0.370 ? 0.030 ns/op > > > So, both `Optional` variants appears to support constant folding. I don't think we can drawn that conclusion just based on the speed. For the non-constant folded cases, this would be 2 loads and an xor. I don't see how C2 would be allowed to constant fold the loads if the value is `null`, since that's explicitly forbidden by `@Stable` (and there's no easy way around that AFAIK, since the JIT thread may see a partially initialized object, so it conservatively ignores default values). ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2514951017 From jvernee at openjdk.org Wed Nov 12 16:40:02 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Wed, 12 Nov 2025 16:40:02 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v24] In-Reply-To: References: Message-ID: On Mon, 10 Nov 2025 14:59:03 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Add @AOTSafeClassInitializer src/java.base/share/classes/jdk/internal/lang/LazyConstantImpl.java line 47: > 45: > 46: // Unsafe allows `LazyConstant` instances to be used early in the boot sequence > 47: static final Unsafe UNSAFE = Unsafe.getUnsafe(); Suggestion: private static final Unsafe UNSAFE = Unsafe.getUnsafe(); test/jdk/java/lang/LazyConstant/LazyConstantSafePublicationTest.java line 117: > 115: @Test > 116: void mainTest() { > 117: CONSTANTS.set(constants()); Instead of passing this through a static field, why not just pass it through the constructor of Producer and Consumer? (which are created below) test/micro/org/openjdk/bench/java/lang/stable/StableMapSingleBenchmark.java line 66: > 64: private static final Map MAP_ENUM = Map.ofLazy(EnumSet.allOf(MyEnum.class), MyEnum::ordinal); > 65: private static final Map> MAP_ENUM_OPTIONAL = Map.ofLazy(EnumSet.allOf(MyEnum.class), e -> Optional.of(e.ordinal())); > 66: private static final Function FUNCTION = MAP::get; I suppose the function variants are not very interesting to test, since they just delegate to Map::get, Maybe consider removing them ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2514957700 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2514930623 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2514913683 From jlahoda at openjdk.org Wed Nov 12 17:33:15 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 12 Nov 2025 17:33:15 GMT Subject: RFR: 8371248: Crash in -Xdoclint with invalid @link Message-ID: The attribution of javadoc links fails with an NPE if the link is like `{@link double.NAN Bad}` - it tries to dereference the `double`, which obviously cannot work. This PR mostly just adds checks that will stop the attribution, and return `null`. Note that for `{@link double Class}` the existing code does not crash and returns the internal a `TypeElement` corresponding to the `double`. This is a weird quirk of this API, and is preserved with this PR (although a test is added for it into `test/langtools/tools/javac/doctree/ReferenceTest.java`). ------------- Commit messages: - Cleanup. - Whitespace tweak. - More tests - More conservative fix. - 8371248: Crash in -Xdoclint with invalid @link Changes: https://git.openjdk.org/jdk/pull/28272/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28272&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8371248 Stats: 13 lines in 3 files changed: 10 ins; 0 del; 3 mod Patch: https://git.openjdk.org/jdk/pull/28272.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28272/head:pull/28272 PR: https://git.openjdk.org/jdk/pull/28272 From cushon at openjdk.org Wed Nov 12 17:56:07 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 12 Nov 2025 17:56:07 GMT Subject: RFR: 8371248: Crash in -Xdoclint with invalid @link In-Reply-To: References: Message-ID: On Wed, 12 Nov 2025 17:26:00 GMT, Jan Lahoda wrote: > The attribution of javadoc links fails with an NPE if the link is like `{@link double.NAN Bad}` - it tries to dereference the `double`, which obviously cannot work. > > This PR mostly just adds checks that will stop the attribution, and return `null`. > > Note that for `{@link double Class}` the existing code does not crash and returns the internal a `TypeElement` corresponding to the `double`. This is a weird quirk of this API, and is preserved with this PR (although a test is added for it into `test/langtools/tools/javac/doctree/ReferenceTest.java`). test/langtools/tools/javac/doctree/ReferenceTest.java line 90: > 88: * {@link double#NAN Bad} > 89: * {@link double#double Bad} > 90: * {@link java.base/double Bad} I also some crashes in non-primitive examples like * {@link List.of} * {@link Optional.empty} * {@link Map.Entry} This PR also fixes them, but maybe consider adding more tests like that, unless it's already covered? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28272#discussion_r2519258043 From duke at openjdk.org Wed Nov 12 21:49:10 2025 From: duke at openjdk.org (ExE Boss) Date: Wed, 12 Nov 2025 21:49:10 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v25] In-Reply-To: References: Message-ID: On Wed, 12 Nov 2025 10:07:39 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 112 commits: > > - Clarify toString spec > - Merge branch 'master' into lazy-constants > - Add @AOTSafeClassInitializer > - Address comments in PR > - Fix merge mistake > - Merge master > - Rework toString implementations > - Update after doc comments > - Merge branch 'master' into lazy-constants > - Revert the AbstractMap.keySet @Stable annotation > - ... and 102 more: https://git.openjdk.org/jdk/compare/76a1109d...1f439bec src/java.base/share/classes/java/util/LazyCollections.java line 509: > 507: return mutex; > 508: } > 509: // Protect against racy stores of mutexe candidates Suggestion: // Protect against racy stores of mutex candidates ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2518540555 From duke at openjdk.org Wed Nov 12 21:49:12 2025 From: duke at openjdk.org (ExE Boss) Date: Wed, 12 Nov 2025 21:49:12 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v25] In-Reply-To: References: Message-ID: On Wed, 12 Nov 2025 16:33:40 GMT, Jorn Vernee wrote: >> Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 112 commits: >> >> - Clarify toString spec >> - Merge branch 'master' into lazy-constants >> - Add @AOTSafeClassInitializer >> - Address comments in PR >> - Fix merge mistake >> - Merge master >> - Rework toString implementations >> - Update after doc comments >> - Merge branch 'master' into lazy-constants >> - Revert the AbstractMap.keySet @Stable annotation >> - ... and 102 more: https://git.openjdk.org/jdk/compare/76a1109d...1f439bec > > src/java.base/share/classes/java/util/LazyCollections.java line 578: > >> 576: if (t == null) { >> 577: final T newValue = switch (functionHolder.function()) { >> 578: case Supplier sup -> (T) sup.get(); > > Is the held function ever a Supplier? I don't see a FunctionHolder being created with one. This?is from?when `FunctionHolder` was?located in?the?`jdk.internal.lang.stable` package in?[GH?25878], and?was?used to?implement the?computing?function freeing?mechanism in?[`StableValue?::supplier(?)`]. [GH?25878]: https://github.com/openjdk/jdk/pull/25878 [`StableValue?::supplier(?)`]: https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/StableValue.html#supplier(java.util.function.Supplier) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2519902578 From vromero at openjdk.org Wed Nov 12 22:26:38 2025 From: vromero at openjdk.org (Vicente Romero) Date: Wed, 12 Nov 2025 22:26:38 GMT Subject: RFR: 8371480: VerifyError after JDK-8369654 Message-ID: It seems like the fix for JDK-8369654 went too far simplifying the new algo equivalent to the more complex idiom: `erasure(lub(t))` As defined in the mentioned fix, it could happen that the list of erased supertypes lists interfaces first followed by classes. Getting the first element in this list would yield an interface which won't then be equivalent to the idiom it is replacing. The current fix adds another operation that should minimize the list of supertypes and sort them classes first and then interfaces. TIA ------------- Commit messages: - 8371480: VerifyError after JDK-8369654 Changes: https://git.openjdk.org/jdk/pull/28276/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28276&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8371480 Stats: 142 lines in 3 files changed: 133 ins; 0 del; 9 mod Patch: https://git.openjdk.org/jdk/pull/28276.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28276/head:pull/28276 PR: https://git.openjdk.org/jdk/pull/28276 From jlahoda at openjdk.org Thu Nov 13 07:52:19 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 13 Nov 2025 07:52:19 GMT Subject: RFR: 8371248: Crash in -Xdoclint with invalid @link [v2] In-Reply-To: References: Message-ID: > The attribution of javadoc links fails with an NPE if the link is like `{@link double.NAN Bad}` - it tries to dereference the `double`, which obviously cannot work. > > This PR mostly just adds checks that will stop the attribution, and return `null`. > > Note that for `{@link double Class}` the existing code does not crash and returns the internal a `TypeElement` corresponding to the `double`. This is a weird quirk of this API, and is preserved with this PR (although a test is added for it into `test/langtools/tools/javac/doctree/ReferenceTest.java`). Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: More appropriate handling of parameterized types in Attr.attribIdent. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28272/files - new: https://git.openjdk.org/jdk/pull/28272/files/ea99a0f1..3a6f37e2 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28272&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28272&range=00-01 Stats: 27 lines in 2 files changed: 27 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/28272.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28272/head:pull/28272 PR: https://git.openjdk.org/jdk/pull/28272 From cstein at openjdk.org Thu Nov 13 08:39:37 2025 From: cstein at openjdk.org (Christian Stein) Date: Thu, 13 Nov 2025 08:39:37 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file [v5] In-Reply-To: References: Message-ID: > Please review this change to include a validation check for expecting an optional JAR manifest entry being the first or second entry in JAR file. As the second entry, it must be only preceeded by an entry for the `META-INF/` directory. Christian Stein has updated the pull request incrementally with one additional commit since the last revision: Use dedicated error messages ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28154/files - new: https://git.openjdk.org/jdk/pull/28154/files/b7389cb6..99e8e320 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28154&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28154&range=03-04 Stats: 19 lines in 3 files changed: 9 ins; 0 del; 10 mod Patch: https://git.openjdk.org/jdk/pull/28154.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28154/head:pull/28154 PR: https://git.openjdk.org/jdk/pull/28154 From cstein at openjdk.org Thu Nov 13 08:45:31 2025 From: cstein at openjdk.org (Christian Stein) Date: Thu, 13 Nov 2025 08:45:31 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file [v4] In-Reply-To: References: Message-ID: On Wed, 12 Nov 2025 14:55:02 GMT, Lance Andersen wrote: >> Christian Stein has updated the pull request incrementally with one additional commit since the last revision: >> >> Add comment to test > > test/jdk/tools/jar/ValidatorTest.java line 315: > >> 313: /** >> 314: * Validates that the LOC MANIFEST.MF entries are at the expected positions. >> 315: * > > Thank you for adding a comment. I might suggest adding a little more clarity or point to JarInputStream docs as the Manifest Location for JarFile is not an issue. > > The issue boils down to the fact that JarInputStream walks the LOC sequentially and because of this there is the limitation on the location of where the Manifest can live. > > Not a big deal overall and I will leave it to you. It is just no obvious to someone who is working in this area the 1st time as this issue is not directly related to the Zip specification, but is a JarInputStream limitation Addressed both, better error messages and the test comment in https://github.com/openjdk/jdk/pull/28154/commits/99e8e3200beac1fea0d32df10d457416773283f3 ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28154#discussion_r2522351147 From jlahoda at openjdk.org Thu Nov 13 10:47:12 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 13 Nov 2025 10:47:12 GMT Subject: RFR: 8371248: Crash in -Xdoclint with invalid @link [v3] In-Reply-To: References: Message-ID: > The attribution of javadoc links fails with an NPE if the link is like `{@link double.NAN Bad}` - it tries to dereference the `double`, which obviously cannot work. > > This PR mostly just adds checks that will stop the attribution, and return `null`. > > Note that for `{@link double Class}` the existing code does not crash and returns the internal a `TypeElement` corresponding to the `double`. This is a weird quirk of this API, and is preserved with this PR (although a test is added for it into `test/langtools/tools/javac/doctree/ReferenceTest.java`). Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Fixing test. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28272/files - new: https://git.openjdk.org/jdk/pull/28272/files/3a6f37e2..8fb68a3d Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28272&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28272&range=01-02 Stats: 12 lines in 2 files changed: 0 ins; 5 del; 7 mod Patch: https://git.openjdk.org/jdk/pull/28272.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28272/head:pull/28272 PR: https://git.openjdk.org/jdk/pull/28272 From abimpoudis at openjdk.org Thu Nov 13 11:11:43 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Thu, 13 Nov 2025 11:11:43 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v5] In-Reply-To: References: Message-ID: On Fri, 7 Nov 2025 09:56:44 GMT, Jan Lahoda wrote: >> Consider code like: >> >> package test; >> public class Test { >> private int test(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> ``` >> >> This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> The goal of this PR is to improve the error, at least in some cases to something along these lines: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> missing patterns: >> test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) >> 1 error >> >> >> The (very simplified) way it works in a recursive (or induction) way: >> - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. >> - for a current missing pattern, try to enhance it: >> - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. >> - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. >> >> This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. >> >> There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. >> >> Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. >> >> There's also an open possibility for select tools to... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Reflecting review comments. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 699: > 697: TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases); > 698: if (exhaustiveSwitch) { > 699: tree.isExhaustive |= exhaustiveness.exhausts(tree.selector, tree.cases); This `|=` turned into `=`. Is that correct? I think so. Now it is guarded by `tree.isExhaustive` itself right? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2523019092 From jlahoda at openjdk.org Thu Nov 13 11:35:52 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 13 Nov 2025 11:35:52 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v9] In-Reply-To: References: Message-ID: > Consider this code: > > $ cat Test.java > package test; > public class Test { > private int test1(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > case Root(R2(R2 _), R2 _) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > > > javac (JDK 25) will produce a compile-time error for this code: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. > > One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. > > Such path exists here (every line shows a set of patterns that is being transformed): > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ > Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) > Root(R2 _, R2 _) > => > Root _ > => > exhaustive > > > The problem here is that in the first step, javac chooses this path: > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) > Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) > => dead end, as there are no two patterns that would have the same nested pattern in the same component > > > If javac would do full backtracking, it could go back, and choose the other path, and find out the switch is exhaustive. But, full naive backtracking is, I think, prohibitively too slow for even relatively small swit... Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Improving test reroducibility. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27247/files - new: https://git.openjdk.org/jdk/pull/27247/files/e6a3f0da..dcf8202b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27247&range=08 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27247&range=07-08 Stats: 2 lines in 1 file changed: 1 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/27247.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27247/head:pull/27247 PR: https://git.openjdk.org/jdk/pull/27247 From abimpoudis at openjdk.org Thu Nov 13 11:41:15 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Thu, 13 Nov 2025 11:41:15 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v5] In-Reply-To: References: Message-ID: On Fri, 7 Nov 2025 09:56:44 GMT, Jan Lahoda wrote: >> Consider code like: >> >> package test; >> public class Test { >> private int test(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> ``` >> >> This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> The goal of this PR is to improve the error, at least in some cases to something along these lines: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> missing patterns: >> test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) >> 1 error >> >> >> The (very simplified) way it works in a recursive (or induction) way: >> - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. >> - for a current missing pattern, try to enhance it: >> - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. >> - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. >> >> This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. >> >> There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. >> >> Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. >> >> There's also an open possibility for select tools to... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Reflecting review comments. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 1023: > 1021: > 1022: Set combinedPatterns = > 1023: joinSets(basePatterns, replace(inMissingPatterns, toExpand, reducedAdded)); Suggestion: Set combinedPatterns = Stream.concat(basePatterns.stream(), replace(inMissingPatterns, toExpand, reducedAdded).stream()) .collect(Collectors.toSet()); Would something like that work, just to avoid the indirection in `joinSets` which is used only once? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 1035: > 1033: /* > 1034: * Sort patterns so that those that those that are prefered for removal > 1035: * are in front of those that are preferred to remain (when there's a choice). Suggestion: * Sort patterns so that those that are preferred for removal are in front * of those that are preferred to remain (when there's a choice). src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 1117: > 1115: } > 1116: > 1117: //assert? Address this todo? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 1137: > 1135: } > 1136: } > 1137: Assert.check(index != (-1)); Small suggestion for understanding better what the assertion would imply. Suggestion: // 'index' must be one of rootPatternRecord.nested; if not, `isUnderRoot` is inconsistent. Assert.check(index != (-1)); src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 1179: > 1177: * with values from {@code updatedNestedPatterns}. Resulting {@code RecordPatterns}s > 1178: * are sent to {@code target}. > 1179: */ /* * Using {@code basePattern} as a starting point, generate new {@code * RecordPattern}s, such that all corresponding components but one, are the * same. The component described by the {@code replaceComponent} index is * replaced with all {@code PatternDescription}s taken from {@code * updatedNestedPatterns} and the resulting {@code RecordPatterns}s are sent * to {@code target}. */ src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 1197: > 1195: > 1196: /* The stricness of determining the equivalent of patterns, used in > 1197: * nestedComponentsEquivalent. Also in `computeCoverage`. Can you provide an example/sentence of two strictly equivalent patterns and two loosely equivalent? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2523091742 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2523095311 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2523107981 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2523121185 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2523080301 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2523051094 From jpai at openjdk.org Thu Nov 13 12:08:46 2025 From: jpai at openjdk.org (Jaikiran Pai) Date: Thu, 13 Nov 2025 12:08:46 GMT Subject: RFR: 8173970: jar tool should have a way to extract to a directory [v16] In-Reply-To: References: Message-ID: <1VIe_2nVpu5ukGbis6X1kKk8Q7rq0C6rIJsPMvlNuFg=.cbdd73f1-bf34-42f9-b2ee-59da75252033@github.com> On Wed, 12 Nov 2025 14:59:27 GMT, Jesse Glick wrote: >> Do we need to create a bug to check the help output? > > Does not seem worth a backport, just noting this for the record. I vaguely remember this text which says "-C" is valid in any mode was discussed (as an existing inaccuracy) when the changes in this PR were being discussed. But I can't find that discussion anywhere right now. I do think that we need to address this text issue for older releases since this text prominently shows up both in the help output as well as the man page for example https://docs.oracle.com/en/java/javase/21/docs/specs/man/jar.html#operation-modifiers-valid-in-any-mode. I'll file an issue shortly. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/2752#discussion_r2523209954 From jpai at openjdk.org Thu Nov 13 12:38:28 2025 From: jpai at openjdk.org (Jaikiran Pai) Date: Thu, 13 Nov 2025 12:38:28 GMT Subject: RFR: 8173970: jar tool should have a way to extract to a directory [v16] In-Reply-To: <1VIe_2nVpu5ukGbis6X1kKk8Q7rq0C6rIJsPMvlNuFg=.cbdd73f1-bf34-42f9-b2ee-59da75252033@github.com> References: <1VIe_2nVpu5ukGbis6X1kKk8Q7rq0C6rIJsPMvlNuFg=.cbdd73f1-bf34-42f9-b2ee-59da75252033@github.com> Message-ID: On Thu, 13 Nov 2025 12:05:57 GMT, Jaikiran Pai wrote: >> Does not seem worth a backport, just noting this for the record. > > I vaguely remember this text which says "-C" is valid in any mode was discussed (as an existing inaccuracy) when the changes in this PR were being discussed. But I can't find that discussion anywhere right now. I do think that we need to address this text issue for older releases since this text prominently shows up both in the help output as well as the man page for example https://docs.oracle.com/en/java/javase/21/docs/specs/man/jar.html#operation-modifiers-valid-in-any-mode. I'll file an issue shortly. I've filed https://bugs.openjdk.org/browse/JDK-8371796 ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/2752#discussion_r2523298438 From lancea at openjdk.org Thu Nov 13 12:41:04 2025 From: lancea at openjdk.org (Lance Andersen) Date: Thu, 13 Nov 2025 12:41:04 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file [v5] In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 08:39:37 GMT, Christian Stein wrote: >> Please review this change to include a validation check for expecting an optional JAR manifest entry being the first or second entry in JAR file. As the second entry, it must be only preceeded by an entry for the `META-INF/` directory. > > Christian Stein has updated the pull request incrementally with one additional commit since the last revision: > > Use dedicated error messages thank you for the additional clarifications. I think we are in a good place ------------- Marked as reviewed by lancea (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28154#pullrequestreview-3459597265 From amaembo at gmail.com Thu Nov 13 12:59:26 2025 From: amaembo at gmail.com (Tagir Valeev) Date: Thu, 13 Nov 2025 13:59:26 +0100 Subject: Lambda with anonymous or local class inside unnecessarily captures 'this' Message-ID: Hello! I was playing with lambda instance deduplication and come up with the following set of test cases: import java.util.function.Supplier; public final class CapturingLambda { Runnable empty() { return () -> {}; } Runnable simple() { return () -> { System.out.println("simple"); }; } Runnable withRunnableInside() { return () -> { Runnable r = () -> {}; r.run(); }; } Runnable withAnonymousRunnableInside() { return () -> { Runnable r = new Runnable() { @Override public void run() { } }; r.run(); }; } Runnable withLocalClassInside() { return () -> { class Local {} new Local(); }; } Runnable withLocalClassInsideNoInstance() { return () -> { class Local {} }; } void checkDeduplicated(String name, Supplier lambdaSupplier) { Runnable lambda1 = lambdaSupplier.get(); Runnable lambda2 = lambdaSupplier.get(); if (lambda1 == lambda2) { System.out.println("Deduplicated: "+name); } else { System.out.println("Not deduplicated: "+name); } } private void test() { checkDeduplicated("empty", this::empty); checkDeduplicated("simple", this::simple); checkDeduplicated("withRunnableInside", this::withRunnableInside); checkDeduplicated("withAnonymousRunnableInside", this::withAnonymousRunnableInside); checkDeduplicated("withLocalClassInside", this::withLocalClassInside); checkDeduplicated("withLocalClassInsideNoInstance", this::withLocalClassInsideNoInstance); } public static void main(String[] args) { new CapturingLambda().test(); } } Here, checkDeduplicated checks whether the particular lambda is deduplicated when returned several times. We know that lambdas are deduplicated if they don't capture anything. The output of this code in Java 24 and Java 25 is the following: Deduplicated: empty Deduplicated: simple Deduplicated: withRunnableInside Not deduplicated: withAnonymousRunnableInside Not deduplicated: withLocalClassInside Deduplicated: withLocalClassInsideNoInstance (side note: in Java 23 and below, withLocalClassInsideNoInstance is Not deduplicated) The problem is that lambdas returned from withAnonymousRunnableInside and withLocalClassInside capture 'this', thus not deduplicated. For example, here's the generated bytecode for withLocalClassInside: private void lambda$withLocalClassInside$0(); descriptor: ()V flags: (0x1002) ACC_PRIVATE, ACC_SYNTHETIC Code: stack=3, locals=1, args_size=1 0: new #73 // class com/example/CapturingLambda$1Local 3: dup 4: aload_0 5: invokespecial #75 // Method com/example/CapturingLambda$1Local."":(Lcom/example/CapturingLambda;)V 8: pop 9: return So 'this' is passed to the generated constructor of the local class CapturingLambda$1Local. However, inside the constructor, the only thing we do with this parameter is check it against null: com.example.CapturingLambda$1Local(com.example.CapturingLambda); descriptor: (Lcom/example/CapturingLambda;)V flags: (0x0000) Code: stack=2, locals=2, args_size=2 0: aload_1 1: dup 2: invokestatic #1 // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object; 5: pop 6: pop 7: aload_0 8: invokespecial #7 // Method java/lang/Object."":()V 11: return Is it really necessary? I understand that the mandated parameter can be probably helpful to maintain the (unspecified) binary compatibility with pre-Java-18 class files not to break the reflection code. However, can we probably omit the null-check and pass null here? This would help to deduplicate lambda instances more and remove the unnecessary strong reference to the outer object. Currently, the lambda cannot outlive the enclosing object, and this looks sad. What do you think? With best regards, Tagir Valeev -------------- next part -------------- An HTML attachment was scrubbed... URL: From hannesw at openjdk.org Thu Nov 13 13:58:16 2025 From: hannesw at openjdk.org (Hannes =?UTF-8?B?V2FsbG7DtmZlcg==?=) Date: Thu, 13 Nov 2025 13:58:16 GMT Subject: RFR: 8371248: Crash in -Xdoclint with invalid @link [v3] In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 10:47:12 GMT, Jan Lahoda wrote: >> The attribution of javadoc links fails with an NPE if the link is like `{@link double.NAN Bad}` - it tries to dereference the `double`, which obviously cannot work. >> >> This PR mostly just adds checks that will stop the attribution, and return `null`. >> >> Note that for `{@link double Class}` the existing code does not crash and returns the internal a `TypeElement` corresponding to the `double`. This is a weird quirk of this API, and is preserved with this PR (although a test is added for it into `test/langtools/tools/javac/doctree/ReferenceTest.java`). > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Fixing test. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java line 41: > 39: import com.sun.source.tree.MemberSelectTree; > 40: import com.sun.source.tree.ParameterizedTypeTree; > 41: import com.sun.source.tree.PrimitiveTypeTree; These imports are no longer needed since you removed the respective visitor methods. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28272#discussion_r2523563668 From mcimadamore at openjdk.org Thu Nov 13 14:00:02 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 13 Nov 2025 14:00:02 GMT Subject: RFR: 8371480: VerifyError after JDK-8369654 In-Reply-To: References: Message-ID: On Wed, 12 Nov 2025 22:19:41 GMT, Vicente Romero wrote: > It seems like the fix for JDK-8369654 went too far simplifying the new algo equivalent to the more complex idiom: `erasure(lub(t))` > As defined in the mentioned fix, it could happen that the list of erased supertypes lists interfaces first followed by classes. Getting the first element in this list would yield an interface which won't then be equivalent to the idiom it is replacing. The current fix adds another operation that should minimize the list of supertypes and sort them classes first and then interfaces. > > TIA Looks good! ------------- Marked as reviewed by mcimadamore (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28276#pullrequestreview-3459927228 From jlahoda at openjdk.org Thu Nov 13 14:25:04 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 13 Nov 2025 14:25:04 GMT Subject: RFR: 8371248: Crash in -Xdoclint with invalid @link [v4] In-Reply-To: References: Message-ID: > The attribution of javadoc links fails with an NPE if the link is like `{@link double.NAN Bad}` - it tries to dereference the `double`, which obviously cannot work. > > This PR mostly just adds checks that will stop the attribution, and return `null`. > > Note that for `{@link double Class}` the existing code does not crash and returns the internal a `TypeElement` corresponding to the `double`. This is a weird quirk of this API, and is preserved with this PR (although a test is added for it into `test/langtools/tools/javac/doctree/ReferenceTest.java`). Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Removing unnecessary imports as suggested. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28272/files - new: https://git.openjdk.org/jdk/pull/28272/files/8fb68a3d..669251e7 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28272&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28272&range=02-03 Stats: 2 lines in 1 file changed: 0 ins; 2 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/28272.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28272/head:pull/28272 PR: https://git.openjdk.org/jdk/pull/28272 From jlahoda at openjdk.org Thu Nov 13 14:25:06 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 13 Nov 2025 14:25:06 GMT Subject: RFR: 8371248: Crash in -Xdoclint with invalid @link [v3] In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 13:54:53 GMT, Hannes Walln?fer wrote: >> Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: >> >> Fixing test. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java line 41: > >> 39: import com.sun.source.tree.MemberSelectTree; >> 40: import com.sun.source.tree.ParameterizedTypeTree; >> 41: import com.sun.source.tree.PrimitiveTypeTree; > > These imports are no longer needed since you removed the respective visitor methods. Thanks, fixed. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28272#discussion_r2523652858 From jlahoda at openjdk.org Thu Nov 13 14:25:09 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 13 Nov 2025 14:25:09 GMT Subject: RFR: 8371248: Crash in -Xdoclint with invalid @link [v4] In-Reply-To: References: Message-ID: <2V4J_m1DQ6K5yeG4u_fMWs8LRcRELL-rD6jFbEb0xZU=.fc73b64f-1511-4407-907b-6099a04d1540@github.com> On Wed, 12 Nov 2025 17:53:09 GMT, Liam Miller-Cushon wrote: >> Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: >> >> Removing unnecessary imports as suggested. > > test/langtools/tools/javac/doctree/ReferenceTest.java line 90: > >> 88: * {@link double#NAN Bad} >> 89: * {@link double#double Bad} >> 90: * {@link java.base/double Bad} > > I also saw some crashes in non-primitive examples like > > > * {@link List.of} > * {@link Optional.empty} > * {@link Map.Entry} > > > This PR also fixes them, but maybe consider adding more tests like that, unless it's already covered? I've added some tests along these lines. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28272#discussion_r2523654046 From cushon at openjdk.org Thu Nov 13 14:25:10 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Thu, 13 Nov 2025 14:25:10 GMT Subject: RFR: 8371248: Crash in -Xdoclint with invalid @link [v4] In-Reply-To: <2V4J_m1DQ6K5yeG4u_fMWs8LRcRELL-rD6jFbEb0xZU=.fc73b64f-1511-4407-907b-6099a04d1540@github.com> References: <2V4J_m1DQ6K5yeG4u_fMWs8LRcRELL-rD6jFbEb0xZU=.fc73b64f-1511-4407-907b-6099a04d1540@github.com> Message-ID: On Thu, 13 Nov 2025 14:20:11 GMT, Jan Lahoda wrote: >> test/langtools/tools/javac/doctree/ReferenceTest.java line 90: >> >>> 88: * {@link double#NAN Bad} >>> 89: * {@link double#double Bad} >>> 90: * {@link java.base/double Bad} >> >> I also saw some crashes in non-primitive examples like >> >> >> * {@link List.of} >> * {@link Optional.empty} >> * {@link Map.Entry} >> >> >> This PR also fixes them, but maybe consider adding more tests like that, unless it's already covered? > > I've added some tests along these lines. Thanks! Looks good to me. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28272#discussion_r2523668727 From hannesw at openjdk.org Thu Nov 13 15:16:21 2025 From: hannesw at openjdk.org (Hannes =?UTF-8?B?V2FsbG7DtmZlcg==?=) Date: Thu, 13 Nov 2025 15:16:21 GMT Subject: RFR: 8371248: Crash in -Xdoclint with invalid @link [v4] In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 14:25:04 GMT, Jan Lahoda wrote: >> The attribution of javadoc links fails with an NPE if the link is like `{@link double.NAN Bad}` - it tries to dereference the `double`, which obviously cannot work. >> >> This PR mostly just adds checks that will stop the attribution, and return `null`. >> >> Note that for `{@link double Class}` the existing code does not crash and returns the internal a `TypeElement` corresponding to the `double`. This is a weird quirk of this API, and is preserved with this PR (although a test is added for it into `test/langtools/tools/javac/doctree/ReferenceTest.java`). > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Removing unnecessary imports as suggested. Looks good to me. test/langtools/tools/javac/doctree/ReferenceTest.java line 111: > 109: * {@link java.base/java.util.Map.Entry.getKey Bad} > 110: * {@link java.base/java.util.Map.Entry#getKey Bad} > 111: * {@link java.base/java.util.Map.Entry#setValue(Object) Bad} Is there a reason parameterized types don't work with modules, or is it just an implementation quirk? Not that it matters much as it is a rather unlikely corner case. ------------- Marked as reviewed by hannesw (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28272#pullrequestreview-3460274938 PR Review Comment: https://git.openjdk.org/jdk/pull/28272#discussion_r2523845287 From vromero at openjdk.org Thu Nov 13 15:31:32 2025 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 13 Nov 2025 15:31:32 GMT Subject: RFR: 8371480: VerifyError after JDK-8369654 In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 13:57:27 GMT, Maurizio Cimadamore wrote: > Looks good! thanks for the review! ------------- PR Comment: https://git.openjdk.org/jdk/pull/28276#issuecomment-3528345372 From vromero at openjdk.org Thu Nov 13 15:31:34 2025 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 13 Nov 2025 15:31:34 GMT Subject: Integrated: 8371480: VerifyError after JDK-8369654 In-Reply-To: References: Message-ID: <6Yjf9Zmz52hI2yW4da_54Y6UFdtaPLFQPRh4YKkp7lM=.b3bc5e3e-4d74-46d4-84bc-b57cdfc79490@github.com> On Wed, 12 Nov 2025 22:19:41 GMT, Vicente Romero wrote: > It seems like the fix for JDK-8369654 went too far simplifying the new algo equivalent to the more complex idiom: `erasure(lub(t))` > As defined in the mentioned fix, it could happen that the list of erased supertypes lists interfaces first followed by classes. Getting the first element in this list would yield an interface which won't then be equivalent to the idiom it is replacing. The current fix adds another operation that should minimize the list of supertypes and sort them classes first and then interfaces. > > TIA This pull request has now been integrated. Changeset: 8102f436 Author: Vicente Romero URL: https://git.openjdk.org/jdk/commit/8102f436f5586253302cd8cef49bfe2b4af41693 Stats: 142 lines in 3 files changed: 133 ins; 0 del; 9 mod 8371480: VerifyError after JDK-8369654 Reviewed-by: mcimadamore ------------- PR: https://git.openjdk.org/jdk/pull/28276 From cstein at openjdk.org Thu Nov 13 16:20:38 2025 From: cstein at openjdk.org (Christian Stein) Date: Thu, 13 Nov 2025 16:20:38 GMT Subject: RFR: 8371470: Java Launcher does not fail when running compact java-file with private no-arg constructor [v2] In-Reply-To: <88t6iQiwL_FM1LOuw6-OgiGZTbVSUz95hZnlNoEpIiU=.4ad93426-b6ce-4530-813d-7e1799e1564d@github.com> References: <88t6iQiwL_FM1LOuw6-OgiGZTbVSUz95hZnlNoEpIiU=.4ad93426-b6ce-4530-813d-7e1799e1564d@github.com> Message-ID: > Please review this change to synchronize the behaviour in `java`'s source launch mode to fail when a non-arg constructor with `private` access modifier is defined - like it does in class launch mode. > > Find the prior-art check performed in class launch mode at [LauncherHelper.java#L958-L961](https://github.com/openjdk/jdk/blob/8102f436f5586253302cd8cef49bfe2b4af41693/src/java.base/share/classes/sun/launcher/LauncherHelper.java#L958-L961): > > > Constructor constructor = mainClass.getDeclaredConstructor(); > if (Modifier.isPrivate(constructor.getModifiers())) { > abort(null, "java.launcher.cls.error6", className); > } Christian Stein has updated the pull request incrementally with one additional commit since the last revision: Remove unused method ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28291/files - new: https://git.openjdk.org/jdk/pull/28291/files/5e53ac85..2508305a Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28291&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28291&range=00-01 Stats: 8 lines in 1 file changed: 0 ins; 8 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/28291.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28291/head:pull/28291 PR: https://git.openjdk.org/jdk/pull/28291 From cstein at openjdk.org Thu Nov 13 16:01:22 2025 From: cstein at openjdk.org (Christian Stein) Date: Thu, 13 Nov 2025 16:01:22 GMT Subject: RFR: 8371470: Java Launcher does not fail when running compact java-file with private no-arg constructor Message-ID: <88t6iQiwL_FM1LOuw6-OgiGZTbVSUz95hZnlNoEpIiU=.4ad93426-b6ce-4530-813d-7e1799e1564d@github.com> Please review this change to synchronize the behaviour in `java`'s source launch mode to fail when a non-arg constructor with `private` access modifier is defined - like it does in class launch mode. Find the prior-art check performed in class launch mode at [LauncherHelper.java#L958-L961](https://github.com/openjdk/jdk/blob/8102f436f5586253302cd8cef49bfe2b4af41693/src/java.base/share/classes/sun/launcher/LauncherHelper.java#L958-L961): Constructor constructor = mainClass.getDeclaredConstructor(); if (Modifier.isPrivate(constructor.getModifiers())) { abort(null, "java.launcher.cls.error6", className); } ------------- Commit messages: - 8371470: Java Launcher does not fail when running compact java-file with private no-arg constructor Changes: https://git.openjdk.org/jdk/pull/28291/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28291&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8371470 Stats: 37 lines in 3 files changed: 34 ins; 1 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/28291.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28291/head:pull/28291 PR: https://git.openjdk.org/jdk/pull/28291 From jlahoda at openjdk.org Thu Nov 13 17:07:50 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 13 Nov 2025 17:07:50 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v6] In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 11:07:13 GMT, Aggelos Biboudis wrote: >> Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: >> >> Apply suggestions from code review >> >> Co-authored-by: Aggelos Biboudis > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 699: > >> 697: TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases); >> 698: if (exhaustiveSwitch) { >> 699: tree.isExhaustive |= exhaustiveness.exhausts(tree.selector, tree.cases); > > This `|=` turned into `=`. Is that correct? I think so. Now it is guarded by `tree.isExhaustive` itself right? Yes, this is intentional. There is one more additional `if (!tree.isExhaustive)` test below, which replaces the use of the or (but is faster in case we know the switch is exhaustive). ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2524257070 From jlahoda at openjdk.org Thu Nov 13 17:07:46 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 13 Nov 2025 17:07:46 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v6] In-Reply-To: References: Message-ID: > Consider code like: > > package test; > public class Test { > private int test(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > ``` > > This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > The goal of this PR is to improve the error, at least in some cases to something along these lines: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > missing patterns: > test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) > 1 error > > > The (very simplified) way it works in a recursive (or induction) way: > - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. > - for a current missing pattern, try to enhance it: > - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. > - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. > > This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. > > There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. > > Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. > > There's also an open possibility for select tools to delay the more detailed computation to some later time, although that would need to be tried and eval... Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Apply suggestions from code review Co-authored-by: Aggelos Biboudis ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27256/files - new: https://git.openjdk.org/jdk/pull/27256/files/50ddab0f..75c3cb0b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=04-05 Stats: 8 lines in 1 file changed: 3 ins; 0 del; 5 mod Patch: https://git.openjdk.org/jdk/pull/27256.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27256/head:pull/27256 PR: https://git.openjdk.org/jdk/pull/27256 From jlahoda at openjdk.org Thu Nov 13 17:11:29 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 13 Nov 2025 17:11:29 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v7] In-Reply-To: References: Message-ID: > Consider code like: > > package test; > public class Test { > private int test(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > ``` > > This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > The goal of this PR is to improve the error, at least in some cases to something along these lines: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > missing patterns: > test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) > 1 error > > > The (very simplified) way it works in a recursive (or induction) way: > - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. > - for a current missing pattern, try to enhance it: > - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. > - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. > > This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. > > There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. > > Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. > > There's also an open possibility for select tools to delay the more detailed computation to some later time, although that would need to be tried and eval... Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Cleanup, reflecting review feedback. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27256/files - new: https://git.openjdk.org/jdk/pull/27256/files/75c3cb0b..8c48cf8f Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=06 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=05-06 Stats: 36 lines in 2 files changed: 18 ins; 12 del; 6 mod Patch: https://git.openjdk.org/jdk/pull/27256.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27256/head:pull/27256 PR: https://git.openjdk.org/jdk/pull/27256 From jlahoda at openjdk.org Thu Nov 13 18:56:40 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 13 Nov 2025 18:56:40 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v8] In-Reply-To: References: Message-ID: > Consider code like: > > package test; > public class Test { > private int test(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > ``` > > This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > The goal of this PR is to improve the error, at least in some cases to something along these lines: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > missing patterns: > test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) > 1 error > > > The (very simplified) way it works in a recursive (or induction) way: > - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. > - for a current missing pattern, try to enhance it: > - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. > - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. > > This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. > > There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. > > Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. > > There's also an open possibility for select tools to delay the more detailed computation to some later time, although that would need to be tried and eval... Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Fixing trailing whitespaces. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27256/files - new: https://git.openjdk.org/jdk/pull/27256/files/8c48cf8f..da130717 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=07 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=06-07 Stats: 3 lines in 1 file changed: 0 ins; 0 del; 3 mod Patch: https://git.openjdk.org/jdk/pull/27256.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27256/head:pull/27256 PR: https://git.openjdk.org/jdk/pull/27256 From archie.cobbs at gmail.com Thu Nov 13 21:42:46 2025 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Thu, 13 Nov 2025 15:42:46 -0600 Subject: Lambda with anonymous or local class inside unnecessarily captures 'this' In-Reply-To: References: Message-ID: Hi Tagir, This is speculation here... Possibly the new behavior is a side effect of JDK-8164714 (pr #23875 ) which ensures outer instances get provided as parameters, even if they are not otherwise used, so they can be checked non-null. I believe that parameter would later get detected by this logic in InnerClassLambdaMetafactory, which would cause it to not deduplicate the lambda instance. If the above is true, then to fix this, one could imagine that the metafactory logic might be made smarter, so it could filter out such "null check only" captured outer instances. I'm not sure exactly how that would be detectable... maybe by adding a new boolean BSM flag? -Archie On Thu, Nov 13, 2025 at 7:00?AM Tagir Valeev wrote: > Hello! > > I was playing with lambda instance deduplication and come up with the > following set of test cases: > > import java.util.function.Supplier; > > public final class CapturingLambda { > Runnable empty() { > return () -> {}; > } > > Runnable simple() { > return () -> { > System.out.println("simple"); > }; > } > > Runnable withRunnableInside() { > return () -> { > Runnable r = () -> {}; > r.run(); > }; > } > > Runnable withAnonymousRunnableInside() { > return () -> { > Runnable r = new Runnable() { > @Override > public void run() { > } > }; > r.run(); > }; > } > > Runnable withLocalClassInside() { > return () -> { > class Local {} > new Local(); > }; > } > > Runnable withLocalClassInsideNoInstance() { > return () -> { > class Local {} > }; > } > > void checkDeduplicated(String name, Supplier lambdaSupplier) > { > Runnable lambda1 = lambdaSupplier.get(); > Runnable lambda2 = lambdaSupplier.get(); > if (lambda1 == lambda2) { > System.out.println("Deduplicated: "+name); > } else { > System.out.println("Not deduplicated: "+name); > } > } > > private void test() { > checkDeduplicated("empty", this::empty); > checkDeduplicated("simple", this::simple); > checkDeduplicated("withRunnableInside", this::withRunnableInside); > checkDeduplicated("withAnonymousRunnableInside", > this::withAnonymousRunnableInside); > checkDeduplicated("withLocalClassInside", > this::withLocalClassInside); > checkDeduplicated("withLocalClassInsideNoInstance", > this::withLocalClassInsideNoInstance); > } > > public static void main(String[] args) { > new CapturingLambda().test(); > } > } > > Here, checkDeduplicated checks whether the particular lambda is > deduplicated when returned several times. We know that lambdas are > deduplicated if they don't capture anything. The output of this code in > Java 24 and Java 25 is the following: > > Deduplicated: empty > Deduplicated: simple > Deduplicated: withRunnableInside > Not deduplicated: withAnonymousRunnableInside > Not deduplicated: withLocalClassInside > Deduplicated: withLocalClassInsideNoInstance > > (side note: in Java 23 and below, withLocalClassInsideNoInstance is Not > deduplicated) > > The problem is that lambdas returned from withAnonymousRunnableInside and > withLocalClassInside capture 'this', thus not deduplicated. For example, > here's the generated bytecode for withLocalClassInside: > > private void lambda$withLocalClassInside$0(); > descriptor: ()V > flags: (0x1002) ACC_PRIVATE, ACC_SYNTHETIC > Code: > stack=3, locals=1, args_size=1 > 0: new #73 // class > com/example/CapturingLambda$1Local > 3: dup > 4: aload_0 > 5: invokespecial #75 // Method > com/example/CapturingLambda$1Local."":(Lcom/example/CapturingLambda;)V > 8: pop > 9: return > > So 'this' is passed to the generated constructor of the local class > CapturingLambda$1Local. However, inside the constructor, the only thing we > do with this parameter is check it against null: > > com.example.CapturingLambda$1Local(com.example.CapturingLambda); > descriptor: (Lcom/example/CapturingLambda;)V > flags: (0x0000) > Code: > stack=2, locals=2, args_size=2 > 0: aload_1 > 1: dup > 2: invokestatic #1 // Method > java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object; > 5: pop > 6: pop > 7: aload_0 > 8: invokespecial #7 // Method > java/lang/Object."":()V > 11: return > > Is it really necessary? I understand that the mandated parameter can be > probably helpful to maintain the (unspecified) binary compatibility with > pre-Java-18 class files not to break the reflection code. However, can we > probably omit the null-check and pass null here? This would help to > deduplicate lambda instances more and remove the unnecessary strong > reference to the outer object. Currently, the lambda cannot outlive the > enclosing object, and this looks sad. What do you think? > > With best regards, > Tagir Valeev > -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From duke at openjdk.org Fri Nov 14 07:02:06 2025 From: duke at openjdk.org (Ana Maria Mihalceanu) Date: Fri, 14 Nov 2025 07:02:06 GMT Subject: RFR: 8371470: Java Launcher does not fail when running compact java-file with private no-arg constructor [v2] In-Reply-To: References: <88t6iQiwL_FM1LOuw6-OgiGZTbVSUz95hZnlNoEpIiU=.4ad93426-b6ce-4530-813d-7e1799e1564d@github.com> Message-ID: On Thu, 13 Nov 2025 16:20:38 GMT, Christian Stein wrote: >> Please review this change to synchronize the behaviour in `java`'s source launch mode to fail when a non-arg constructor with `private` access modifier is defined - like it does in class launch mode. >> >> Find the prior-art check performed in class launch mode at [LauncherHelper.java#L958-L961](https://github.com/openjdk/jdk/blob/8102f436f5586253302cd8cef49bfe2b4af41693/src/java.base/share/classes/sun/launcher/LauncherHelper.java#L958-L961): >> >> >> Constructor constructor = mainClass.getDeclaredConstructor(); >> if (Modifier.isPrivate(constructor.getModifiers())) { >> abort(null, "java.launcher.cls.error6", className); >> } > > Christian Stein has updated the pull request incrementally with one additional commit since the last revision: > > Remove unused method Thank you for solving this issue, Christian ? . While not directly related to the core issue of this bug, could you also please check my comment? src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher.properties line 125: > 123: # 0: string > 124: launcher.err.cant.find.constructor=\ > 125: can''t find no argument constructor in class: {0} This is a nitpick, but I noticed the double `'` in the message above. Suggestion: can't find no argument constructor in class: {0} ------------- PR Review: https://git.openjdk.org/jdk/pull/28291#pullrequestreview-3463106346 PR Review Comment: https://git.openjdk.org/jdk/pull/28291#discussion_r2526025421 From cstein at openjdk.org Fri Nov 14 07:37:18 2025 From: cstein at openjdk.org (Christian Stein) Date: Fri, 14 Nov 2025 07:37:18 GMT Subject: RFR: 8371470: Java Launcher does not fail when running compact java-file with private no-arg constructor [v2] In-Reply-To: References: <88t6iQiwL_FM1LOuw6-OgiGZTbVSUz95hZnlNoEpIiU=.4ad93426-b6ce-4530-813d-7e1799e1564d@github.com> Message-ID: On Fri, 14 Nov 2025 06:56:41 GMT, Ana Maria Mihalceanu wrote: >> Christian Stein has updated the pull request incrementally with one additional commit since the last revision: >> >> Remove unused method > > src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher.properties line 125: > >> 123: # 0: string >> 124: launcher.err.cant.find.constructor=\ >> 125: can''t find no argument constructor in class: {0} > > This is a nitpick, but I noticed the double `'` in the message above. > > Suggestion: > > can't find no argument constructor in class: {0} That is the correct syntax, required by `MessageFormat`: [MessageFormat#quoting-rules-in-patterns-heading](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/text/MessageFormat.html#quoting-rules-in-patterns-heading) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28291#discussion_r2526165995 From jlahoda at openjdk.org Fri Nov 14 08:31:54 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 14 Nov 2025 08:31:54 GMT Subject: RFR: 8371309: Diagnostic.getEndPosition can throw an NPE with typical broken code Message-ID: When starting the compiler via API, a `DiagnosticListener` may be provided, to which all reported errors and warnings are reported. The reported diagnostics are represented by `javax.tools.Diagnostic`, which has (among others) method `getEndPosition`, which requires the end-pos-table to be set in the `DiagnosticSource` object for the given file (see `AbstractLog.sourceMap`). But the end-pos-table is only set after the parse is done: https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L702 There are three problems with this: - when a `Diagnostic` is reported by the parser, and the clients code calls `Diagnostic.getEndPosition`, the end-pos-table is not set yet, and the method crashes with an NPE - the end-pos-table is never set for implicitly compiled (parsed) files: https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L840 - when a `Diagnostic` is reported for a tree by the parser, the tree on which the `Diagnostic` appear does not typically have the end position set yet - it is usually set only after the error/warning is reported All those problems used to be hidden by this check: https://github.com/openjdk/jdk/blob/6c48f4ed707bf0b15f9b6098de30db8aae6fa40f/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java#L649 but that has been removed: https://github.com/openjdk/jdk/commit/c793de989facdb532021e1d5ddd01eb0e089b8e6 I have tried to fix this properly, by deferring the errors from the parser to a later point, properly setting the end-pos-table, and handling implicitly parsed files more correctly: https://github.com/openjdk/jdk/compare/master...lahodaj:jdk:JDK-8371309b?expand=1 but this change is a bit involved, and potentially a bit dangerous. So, for now, I propose to reinstate the null check in `TreeInfo.getEndPos`, to restore the JDK 25 behavior, and attempt to do the better solution later, hopefully earlier in the release cycle. ------------- Commit messages: - 8371309: Diagnostic.getEndPosition can throw an NPE with typical broken code Changes: https://git.openjdk.org/jdk/pull/28316/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28316&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8371309 Stats: 194 lines in 2 files changed: 194 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/28316.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28316/head:pull/28316 PR: https://git.openjdk.org/jdk/pull/28316 From nbenalla at openjdk.org Fri Nov 14 09:47:49 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Fri, 14 Nov 2025 09:47:49 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 [v5] In-Reply-To: References: Message-ID: > Get JDK 27 underway. Nizar Benalla has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains seven additional commits since the last revision: - Merge branch 'master' into start-of-release-27 - Updates due to the generate-symbol-data.sh location changing in 8367259 - Updates due to the generate-symbol-data.sh location changing in 8367259 - Merge branch 'master' into start-of-release-27 - update links to JVMS 26 and 27 - add missing enum - initial commit start-of-JDK-27 ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28130/files - new: https://git.openjdk.org/jdk/pull/28130/files/0652d5d3..3d9eb308 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=03-04 Stats: 14293 lines in 184 files changed: 9629 ins; 3659 del; 1005 mod Patch: https://git.openjdk.org/jdk/pull/28130.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28130/head:pull/28130 PR: https://git.openjdk.org/jdk/pull/28130 From mcimadamore at openjdk.org Fri Nov 14 09:48:28 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 09:48:28 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v25] In-Reply-To: References: Message-ID: <_twwdOdK3jZMnAaDPFubJhbEbR_FEK99I4obbpttveU=.21e193fa-067e-4df1-8cff-4cd0fc704e4f@github.com> On Wed, 12 Nov 2025 10:07:39 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 112 commits: > > - Clarify toString spec > - Merge branch 'master' into lazy-constants > - Add @AOTSafeClassInitializer > - Address comments in PR > - Fix merge mistake > - Merge master > - Rework toString implementations > - Update after doc comments > - Merge branch 'master' into lazy-constants > - Revert the AbstractMap.keySet @Stable annotation > - ... and 102 more: https://git.openjdk.org/jdk/compare/76a1109d...1f439bec src/java.base/share/classes/java/lang/LazyConstant.java line 241: > 239: > 240: /** > 241: * {@return if this lazy constant is the same as the provided {@code obj}} maybe add (either in this PR or as follow up) a clarification saying that two different lazy constant that point to the same contents are **not** equals src/java.base/share/classes/java/lang/LazyConstant.java line 280: > 278: * {@code computingFunction} at least until initialization completes successfully. > 279: *

> 280: * If the provided computing function is already an instance of Not sure how I feel about that -- it seems to soft-break equals... ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2526752889 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2526762818 From mcimadamore at openjdk.org Fri Nov 14 09:55:14 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 09:55:14 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v25] In-Reply-To: References: Message-ID: On Wed, 12 Nov 2025 10:07:39 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 112 commits: > > - Clarify toString spec > - Merge branch 'master' into lazy-constants > - Add @AOTSafeClassInitializer > - Address comments in PR > - Fix merge mistake > - Merge master > - Rework toString implementations > - Update after doc comments > - Merge branch 'master' into lazy-constants > - Revert the AbstractMap.keySet @Stable annotation > - ... and 102 more: https://git.openjdk.org/jdk/compare/76a1109d...1f439bec Looks great -- just a couple more javadoc tweaks ;-) src/java.base/share/classes/java/util/List.java line 1233: > 1231: * The returned list's {@linkplain Object#equals(Object) equals()} and > 1232: * {@linkplain Object#hashCode() hashCode()} methods may trigger initialization of one > 1233: * or more lazy elements. The returned list's {@linkplain Object#toString() toString()} I thought we have concluded that all Object methods should behave as those in any other list, to maximize migration opportunities. ------------- PR Review: https://git.openjdk.org/jdk/pull/27605#pullrequestreview-3464050345 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2526787780 From mcimadamore at openjdk.org Fri Nov 14 12:55:31 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 12:55:31 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v8] In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 18:56:40 GMT, Jan Lahoda wrote: >> Consider code like: >> >> package test; >> public class Test { >> private int test(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> ``` >> >> This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> The goal of this PR is to improve the error, at least in some cases to something along these lines: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> missing patterns: >> test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) >> 1 error >> >> >> The (very simplified) way it works in a recursive (or induction) way: >> - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. >> - for a current missing pattern, try to enhance it: >> - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. >> - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. >> >> This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. >> >> There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. >> >> Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. >> >> There's also an open possibility for select tools to... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Fixing trailing whitespaces. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 893: > 891: return currentMissingPatterns; > 892: } else if ((bp.type.tsym.flags_field & Flags.RECORD) != 0 && > 893: //only expand record types into record patterns if there's a chance it may change the outcome I agree with this choice ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2527397118 From mcimadamore at openjdk.org Fri Nov 14 13:21:32 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 13:21:32 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v8] In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 18:56:40 GMT, Jan Lahoda wrote: >> Consider code like: >> >> package test; >> public class Test { >> private int test(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> ``` >> >> This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> The goal of this PR is to improve the error, at least in some cases to something along these lines: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> missing patterns: >> test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) >> 1 error >> >> >> The (very simplified) way it works in a recursive (or induction) way: >> - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. >> - for a current missing pattern, try to enhance it: >> - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. >> - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. >> >> This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. >> >> There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. >> >> Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. >> >> There's also an open possibility for select tools to... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Fixing trailing whitespaces. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 939: > 937: removeUnnecessaryPatterns(selectorType, bp, basePatterns, inMissingPatterns, combinatorialPatterns); > 938: > 939: CoverageResult coverageResult = computeCoverage(targetType, combinatorialPatterns, PatternEquivalence.LOOSE); How can the expansion of a record pattern not cover? E.g. if we start with an exhaustive pattern `R r` and we expand `R` into all its components `R(A1, B1, C1)`, `R(A2, B2, C2)` ... -- how can we get into a situation where we're no longer exhaustive? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2527480880 From mcimadamore at openjdk.org Fri Nov 14 13:34:08 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 13:34:08 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v8] In-Reply-To: References: Message-ID: <8dZbRs3s5I3mI8Iwlq1NW30PJEw8huzJE9zzlCoQrS4=.5e78a559-b585-4eee-b02f-087e586b0f5c@github.com> On Thu, 13 Nov 2025 18:56:40 GMT, Jan Lahoda wrote: >> Consider code like: >> >> package test; >> public class Test { >> private int test(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> ``` >> >> This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> The goal of this PR is to improve the error, at least in some cases to something along these lines: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> missing patterns: >> test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) >> 1 error >> >> >> The (very simplified) way it works in a recursive (or induction) way: >> - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. >> - for a current missing pattern, try to enhance it: >> - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. >> - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. >> >> This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. >> >> There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. >> >> Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. >> >> There's also an open possibility for select tools to... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Fixing trailing whitespaces. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 161: > 159: return enum2Constants.get(enumType).stream().map(c -> enumType.toString() + "." + c.name); > 160: } else { > 161: return Stream.of(pd.toString()); As discussed offline, eager string generation will render the diagnostic arguments completely opaque to the formatter. This would mean that no `where` clauses will be generated, and unambiguous qualifiers will not be omitted. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 832: > 830: Set.of(defaultPattern)); > 831: } catch (TimeoutException ex) { > 832: return ex.missingPatterns != null ? ex.missingPatterns : Set.of(); Instead of a timeout, I wonder if you could instead cut the recursion at a specific threshold. It seems to me that recursing more will provide more precision _at the nested level_, so it's a trade off between when do we want to stop. Overload resolution provides some kind of precedent: error: incompatible types: String cannot be converted to int m("Hello"); ^ Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output 1 error (We "compress" the diagnostic whenever we can somehow figure out if an overload is "better" than the others). Then if you provide the option, you get the full thing: error: no suitable method found for m(String) m("Hello"); ^ method Test.m() is not applicable (actual and formal argument lists differ in length) method Test.m(int) is not applicable (argument mismatch; String cannot be converted to int) method Test.m(int,int) is not applicable (actual and formal argument lists differ in length) method Test.m(int,int,int) is not applicable (actual and formal argument lists differ in length) method Test.m(int,int,int,int) is not applicable (actual and formal argument lists differ in length) method Test.m(int,int,int,int,int) is not applicable (actual and formal argument lists differ in length) method Test.m(int,int,int,int,int,int) is not applicable (actual and formal argument lists differ in length) But, also, maybe putting an upper bound on the recursion, no matter what, might be a good idea? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2527519653 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2527511175 From pminborg at openjdk.org Fri Nov 14 13:35:17 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 14 Nov 2025 13:35:17 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v25] In-Reply-To: References: <-lErHk2PzyJCaPQGrEwCt3nObTrTHs7_p53eBXspUGE=.50dc2375-8769-49a5-9308-ab40132bbd19@github.com> Message-ID: On Tue, 11 Nov 2025 16:48:58 GMT, Jorn Vernee wrote: >> I've added two new benchmarks: >> >> >> private static final LazyConstant> OPTIONAL_42 = LazyConstant.of(() -> Optional.of(42)); >> private static final LazyConstant> OPTIONAL_42_2 = LazyConstant.of(() -> Optional.of(42)); >> private static final LazyConstant> OPTIONAL_EMPTY = LazyConstant.of(Optional::empty); >> private static final LazyConstant> OPTIONAL_EMPTY2 = LazyConstant.of(Optional::empty); >> >> ... >> >> @Benchmark >> public int staticOptional42() { >> return OPTIONAL_42.get().orElseThrow() + OPTIONAL_42_2.get().orElseThrow(); >> } >> >> @Benchmark >> public boolean staticOptionalEmpty() { >> return OPTIONAL_EMPTY.get().isEmpty() ^ OPTIONAL_EMPTY2.get().isEmpty(); >> } >> >> >> >> >> Which gives: >> >> >> Benchmark Mode Cnt Score Error Units >> StableValueBenchmark.staticOptional42 avgt 10 0.354 ? 0.045 ns/op >> >> Benchmark Mode Cnt Score Error Units >> StableValueBenchmark.staticOptionalEmpty avgt 10 0.370 ? 0.030 ns/op >> >> >> So, both `Optional` variants appears to support constant folding. > > I don't think we can drawn that conclusion just based on the speed. For the non-constant folded cases, this would be 2 loads and an xor. > > I don't see how C2 would be allowed to constant fold the loads if the value is `null`, since that's explicitly forbidden by `@Stable` (and there's no easy way around that AFAIK, since the JIT thread may see a partially initialized object, so it conservatively ignores default values). Yes. I think you are right @JornVernee. I've explored several ways to fix this and the simplest one might be to have a sentinel value instead of `null` to flag emptiness. Splitting the class into a bimorphic implementation would not be good for `value` classes (at least not for now), even though the C2 might otherwise be able to optimize the two variants. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2527523848 From mcimadamore at openjdk.org Fri Nov 14 13:37:53 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 13:37:53 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v8] In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 18:56:40 GMT, Jan Lahoda wrote: >> Consider code like: >> >> package test; >> public class Test { >> private int test(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> ``` >> >> This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> The goal of this PR is to improve the error, at least in some cases to something along these lines: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> missing patterns: >> test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) >> 1 error >> >> >> The (very simplified) way it works in a recursive (or induction) way: >> - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. >> - for a current missing pattern, try to enhance it: >> - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. >> - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. >> >> This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. >> >> There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. >> >> Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. >> >> There's also an open possibility for select tools to... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Fixing trailing whitespaces. test/langtools/tools/javac/patterns/ExhaustivenessConvenientErrors.java line 290: > 288: case Triple(_, _, A _) -> 0; > 289: case Triple(A p, C(Nested _, NestedBaseA _), _) -> 0; > 290: case Triple(A p, C(Nested _, NestedBaseB _), C(Underneath _, NestedBaseA _)) -> 0; Where is `Underneath` defined? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2527531368 From mcimadamore at openjdk.org Fri Nov 14 14:25:58 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 14:25:58 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v8] In-Reply-To: <8dZbRs3s5I3mI8Iwlq1NW30PJEw8huzJE9zzlCoQrS4=.5e78a559-b585-4eee-b02f-087e586b0f5c@github.com> References: <8dZbRs3s5I3mI8Iwlq1NW30PJEw8huzJE9zzlCoQrS4=.5e78a559-b585-4eee-b02f-087e586b0f5c@github.com> Message-ID: On Fri, 14 Nov 2025 13:31:01 GMT, Maurizio Cimadamore wrote: >> Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: >> >> Fixing trailing whitespaces. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 161: > >> 159: return enum2Constants.get(enumType).stream().map(c -> enumType.toString() + "." + c.name); >> 160: } else { >> 161: return Stream.of(pd.toString()); > > As discussed offline, eager string generation will render the diagnostic arguments completely opaque to the formatter. This would mean that no `where` clauses will be generated, and unambiguous qualifiers will not be omitted. Also, don't forget `JCDiagnostic.MultilineDiagnostic`, which we use in overloads to render repetitive fragments in tabular format. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2527692180 From mcimadamore at openjdk.org Fri Nov 14 14:17:23 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 14:17:23 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v8] In-Reply-To: References: Message-ID: On Fri, 14 Nov 2025 14:11:39 GMT, Maurizio Cimadamore wrote: >> Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: >> >> Fixing trailing whitespaces. > > test/langtools/tools/javac/patterns/ExhaustivenessConvenientErrors.java line 352: > >> 350: """, >> 351: "test.Test.Root(test.Test.R2 _, test.Test.R2(test.Test.Base _, test.Test.R2 _), test.Test.R2(test.Test.R2 _, test.Test.Base _))"); >> 352: //ideally, the result would be as follow, but it is difficult to split Base on two distinct places: > > With recursion it should be possible -- but I guess the problem becomes, when do you stop? > > e.g. > `{ Base } -> { R1, R2 } -> { R1, R2(Base, Base) } -> ...` Perhaps an idea here (not sure how crazy -- possibly a lot) would be to run an analysis on the original patterns as defined in the source code, and determine the _max depth_, and then expand "up to that depth". So, in the above case, you would know that when you get to `{R1, R2}`, it's "good enough" for the level of depth that is present in the code. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2527664757 From mcimadamore at openjdk.org Fri Nov 14 14:25:56 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 14:25:56 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v8] In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 18:56:40 GMT, Jan Lahoda wrote: >> Consider code like: >> >> package test; >> public class Test { >> private int test(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> ``` >> >> This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> The goal of this PR is to improve the error, at least in some cases to something along these lines: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> missing patterns: >> test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) >> 1 error >> >> >> The (very simplified) way it works in a recursive (or induction) way: >> - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. >> - for a current missing pattern, try to enhance it: >> - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. >> - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. >> >> This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. >> >> There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. >> >> Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. >> >> There's also an open possibility for select tools to... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Fixing trailing whitespaces. I think this is impressive work. In "normal" situations (e.g. switches not too big, or too nested) I can easily imagine the new diagnostics to be a life saver. There's of course a lot of tinkering and followup work that might be possible, to improve the performance of the analysis, or to fine tune the expansion more to the shape of the code. For now, I think I see two more general issues that stick out: * the early flattening to string, which bypasses the diagnostic formatter -- but that should be easy to fix * the timeout-based strategy. We don't have anything like that anywhere else in the compiler. I think it would be preferrable to have a "variable rate" of accuracy, and maybe limit how the analysis is ran, unless the user really wants to discover every detail. But I'm not sure it's always possible. Cutting on recursion might be a good way to put a ceiling on complexity. Another avenue might be to refuse to expand sealed types that have more than N ermitted subclasses. ------------- PR Review: https://git.openjdk.org/jdk/pull/27256#pullrequestreview-3465174562 From mcimadamore at openjdk.org Fri Nov 14 14:17:21 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 14:17:21 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v8] In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 18:56:40 GMT, Jan Lahoda wrote: >> Consider code like: >> >> package test; >> public class Test { >> private int test(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> ``` >> >> This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> The goal of this PR is to improve the error, at least in some cases to something along these lines: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> missing patterns: >> test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) >> 1 error >> >> >> The (very simplified) way it works in a recursive (or induction) way: >> - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. >> - for a current missing pattern, try to enhance it: >> - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. >> - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. >> >> This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. >> >> There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. >> >> Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. >> >> There's also an open possibility for select tools to... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Fixing trailing whitespaces. test/langtools/tools/javac/patterns/ExhaustivenessConvenientErrors.java line 352: > 350: """, > 351: "test.Test.Root(test.Test.R2 _, test.Test.R2(test.Test.Base _, test.Test.R2 _), test.Test.R2(test.Test.R2 _, test.Test.Base _))"); > 352: //ideally, the result would be as follow, but it is difficult to split Base on two distinct places: With recursion it should be possible -- but I guess the problem becomes, when do you stop? e.g. `{ Base } -> { R1, R2 } -> { R1, R2(Base, Base) } -> ...` ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2527654214 From pminborg at openjdk.org Fri Nov 14 14:44:49 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 14 Nov 2025 14:44:49 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v25] In-Reply-To: References: Message-ID: On Wed, 12 Nov 2025 16:02:05 GMT, Jorn Vernee wrote: >> Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 112 commits: >> >> - Clarify toString spec >> - Merge branch 'master' into lazy-constants >> - Add @AOTSafeClassInitializer >> - Address comments in PR >> - Fix merge mistake >> - Merge master >> - Rework toString implementations >> - Update after doc comments >> - Merge branch 'master' into lazy-constants >> - Revert the AbstractMap.keySet @Stable annotation >> - ... and 102 more: https://git.openjdk.org/jdk/compare/76a1109d...1f439bec > > src/java.base/share/classes/java/util/LazyCollections.java line 66: > >> 64: // using `elements.length`. >> 65: @Stable >> 66: private final int size; > > Is this really that important? What about the extra footprint added by the `int` field? We might have many instances of this class, but only one copy of the bytecode. Hrrm. I wonder if the C2 compiler will end up producing equivalent code for the two variants? But there are merits to your argument. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2527753354 From chen.l.liang at oracle.com Fri Nov 14 15:15:47 2025 From: chen.l.liang at oracle.com (Chen Liang) Date: Fri, 14 Nov 2025 15:15:47 +0000 Subject: Lambda with anonymous or local class inside unnecessarily captures 'this' In-Reply-To: References: Message-ID: The situation in which non-member nested classes capture the enclosing instance unconditionally can be treated as an implementation artifact of javac; we discussed this within Oracle a while ago. The enclosing instance capture being the leading parameter and the null check are for linkage, but local and anonymous classes do not have such linkage links, and it should be JLS-compliant that unused enclosing instance capture is dropped altogether. There are local and anonymous classes in early construction context and static context that don't perform enclosing instance capture, yet reflectively they are not distinguished from the ones that do, so I believe the compatibility impact is low. Re Archie: I think Tagir means that for 23 and below, the lambdas with local or anonymous classes are still captured. It is interesting withLocalClassInsideNoInstance() is suddenly deduplicated. P.S. "Deduplication" is a confusing term - in javac I believe it refers to identical lambda expressions reusing the same InvokeDynamic constant (which still generates different call sites per JVMS rules), but in this thread it refers to the singleton lambda instances. -Chen ________________________________ From: compiler-dev on behalf of Archie Cobbs Sent: Thursday, November 13, 2025 3:42 PM To: Tagir Valeev Cc: compiler-dev at openjdk.org Subject: Re: Lambda with anonymous or local class inside unnecessarily captures 'this' Hi Tagir, This is speculation here... Possibly the new behavior is a side effect of JDK-8164714 (pr #23875) which ensures outer instances get provided as parameters, even if they are not otherwise used, so they can be checked non-null. I believe that parameter would later get detected by this logic in InnerClassLambdaMetafactory, which would cause it to not deduplicate the lambda instance. If the above is true, then to fix this, one could imagine that the metafactory logic might be made smarter, so it could filter out such "null check only" captured outer instances. I'm not sure exactly how that would be detectable... maybe by adding a new boolean BSM flag? -Archie On Thu, Nov 13, 2025 at 7:00?AM Tagir Valeev > wrote: Hello! I was playing with lambda instance deduplication and come up with the following set of test cases: import java.util.function.Supplier; public final class CapturingLambda { Runnable empty() { return () -> {}; } Runnable simple() { return () -> { System.out.println("simple"); }; } Runnable withRunnableInside() { return () -> { Runnable r = () -> {}; r.run(); }; } Runnable withAnonymousRunnableInside() { return () -> { Runnable r = new Runnable() { @Override public void run() { } }; r.run(); }; } Runnable withLocalClassInside() { return () -> { class Local {} new Local(); }; } Runnable withLocalClassInsideNoInstance() { return () -> { class Local {} }; } void checkDeduplicated(String name, Supplier lambdaSupplier) { Runnable lambda1 = lambdaSupplier.get(); Runnable lambda2 = lambdaSupplier.get(); if (lambda1 == lambda2) { System.out.println("Deduplicated: "+name); } else { System.out.println("Not deduplicated: "+name); } } private void test() { checkDeduplicated("empty", this::empty); checkDeduplicated("simple", this::simple); checkDeduplicated("withRunnableInside", this::withRunnableInside); checkDeduplicated("withAnonymousRunnableInside", this::withAnonymousRunnableInside); checkDeduplicated("withLocalClassInside", this::withLocalClassInside); checkDeduplicated("withLocalClassInsideNoInstance", this::withLocalClassInsideNoInstance); } public static void main(String[] args) { new CapturingLambda().test(); } } Here, checkDeduplicated checks whether the particular lambda is deduplicated when returned several times. We know that lambdas are deduplicated if they don't capture anything. The output of this code in Java 24 and Java 25 is the following: Deduplicated: empty Deduplicated: simple Deduplicated: withRunnableInside Not deduplicated: withAnonymousRunnableInside Not deduplicated: withLocalClassInside Deduplicated: withLocalClassInsideNoInstance (side note: in Java 23 and below, withLocalClassInsideNoInstance is Not deduplicated) The problem is that lambdas returned from withAnonymousRunnableInside and withLocalClassInside capture 'this', thus not deduplicated. For example, here's the generated bytecode for withLocalClassInside: private void lambda$withLocalClassInside$0(); descriptor: ()V flags: (0x1002) ACC_PRIVATE, ACC_SYNTHETIC Code: stack=3, locals=1, args_size=1 0: new #73 // class com/example/CapturingLambda$1Local 3: dup 4: aload_0 5: invokespecial #75 // Method com/example/CapturingLambda$1Local."":(Lcom/example/CapturingLambda;)V 8: pop 9: return So 'this' is passed to the generated constructor of the local class CapturingLambda$1Local. However, inside the constructor, the only thing we do with this parameter is check it against null: com.example.CapturingLambda$1Local(com.example.CapturingLambda); descriptor: (Lcom/example/CapturingLambda;)V flags: (0x0000) Code: stack=2, locals=2, args_size=2 0: aload_1 1: dup 2: invokestatic #1 // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object; 5: pop 6: pop 7: aload_0 8: invokespecial #7 // Method java/lang/Object."":()V 11: return Is it really necessary? I understand that the mandated parameter can be probably helpful to maintain the (unspecified) binary compatibility with pre-Java-18 class files not to break the reflection code. However, can we probably omit the null-check and pass null here? This would help to deduplicate lambda instances more and remove the unnecessary strong reference to the outer object. Currently, the lambda cannot outlive the enclosing object, and this looks sad. What do you think? With best regards, Tagir Valeev -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From pminborg at openjdk.org Fri Nov 14 15:15:51 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 14 Nov 2025 15:15:51 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v25] In-Reply-To: References: Message-ID: <7emI0lI9l1ZnKE89i3hDeQl4KiaE_GutmkDoIu772Ik=.276d7422-4102-425a-a92f-439134945f60@github.com> On Wed, 12 Nov 2025 16:08:19 GMT, Jorn Vernee wrote: >> Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 112 commits: >> >> - Clarify toString spec >> - Merge branch 'master' into lazy-constants >> - Add @AOTSafeClassInitializer >> - Address comments in PR >> - Fix merge mistake >> - Merge master >> - Rework toString implementations >> - Update after doc comments >> - Merge branch 'master' into lazy-constants >> - Revert the AbstractMap.keySet @Stable annotation >> - ... and 102 more: https://git.openjdk.org/jdk/compare/76a1109d...1f439bec > > src/java.base/share/classes/java/util/LazyCollections.java line 199: > >> 197: final int size = base.size(); >> 198: subListRangeCheck(fromIndex, toIndex, size); >> 199: return new ReverseOrderLazyListView<>(base.subList(size - toIndex, size - fromIndex)); > > Why not this? (maybe add a comment?) > Suggestion: > > return new ReverseOrderLazyListView<>(base.subList(fromIndex, toIndex)); Actually, now that toString() evaluates, we could just get rid of these classes and use the ones in the base class. Great! ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2527855543 From mcimadamore at openjdk.org Fri Nov 14 15:27:31 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 15:27:31 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v8] In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 18:56:40 GMT, Jan Lahoda wrote: >> Consider code like: >> >> package test; >> public class Test { >> private int test(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> ``` >> >> This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> The goal of this PR is to improve the error, at least in some cases to something along these lines: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> missing patterns: >> test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) >> 1 error >> >> >> The (very simplified) way it works in a recursive (or induction) way: >> - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. >> - for a current missing pattern, try to enhance it: >> - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. >> - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. >> >> This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. >> >> There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. >> >> Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. >> >> There's also an open possibility for select tools to... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Fixing trailing whitespaces. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 899: > 897: //have a record pattern, try to expand the binding pattern into a record pattern > 898: //create all possible combinations of record pattern components: > 899: Type[] componentTypes = ((ClassSymbol) bp.type.tsym).getRecordComponents() This same "pattern" of code seems repeated in `makePatternDescription` -- ideally there should be a way to compute the "instantiated" component types ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2527893968 From pminborg at openjdk.org Fri Nov 14 15:35:03 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 14 Nov 2025 15:35:03 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v25] In-Reply-To: References: Message-ID: On Wed, 12 Nov 2025 16:17:37 GMT, Jorn Vernee wrote: >> Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 112 commits: >> >> - Clarify toString spec >> - Merge branch 'master' into lazy-constants >> - Add @AOTSafeClassInitializer >> - Address comments in PR >> - Fix merge mistake >> - Merge master >> - Rework toString implementations >> - Update after doc comments >> - Merge branch 'master' into lazy-constants >> - Revert the AbstractMap.keySet @Stable annotation >> - ... and 102 more: https://git.openjdk.org/jdk/compare/76a1109d...1f439bec > > src/java.base/share/classes/java/util/LazyCollections.java line 433: > >> 431: @Override public V getValue() { >> 432: final int index = map.indexFor(getKey); >> 433: final V v = map.getAcquire(getKey); > > I suppose you could use `orElseCompute` here, since you already have the index Nice. Then we can get rid of the getAquire() method as well. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2527915904 From pminborg at openjdk.org Fri Nov 14 15:41:36 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 14 Nov 2025 15:41:36 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v25] In-Reply-To: References: Message-ID: <6zrll105lMejyo1PAG6cfBFzYt3N2-_9lIK6uP-Wl8A=.3e7908a7-71da-452e-8703-c4b7b5d661c3@github.com> On Wed, 12 Nov 2025 16:32:28 GMT, Jorn Vernee wrote: >> Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 112 commits: >> >> - Clarify toString spec >> - Merge branch 'master' into lazy-constants >> - Add @AOTSafeClassInitializer >> - Address comments in PR >> - Fix merge mistake >> - Merge master >> - Rework toString implementations >> - Update after doc comments >> - Merge branch 'master' into lazy-constants >> - Revert the AbstractMap.keySet @Stable annotation >> - ... and 102 more: https://git.openjdk.org/jdk/compare/76a1109d...1f439bec > > src/java.base/share/classes/java/util/LazyCollections.java line 607: > >> 605: assert Thread.holdsLock(mutex) : index + "didn't hold " + mutex; >> 606: // We know we hold the monitor here so plain semantic is enough >> 607: if (array[index] == null) { > > This should always be true when we get here, right? This is just an extra safety net to emulate a CAS op (while we are holding the monitor). ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2527936851 From acobbs at openjdk.org Fri Nov 14 16:47:03 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Fri, 14 Nov 2025 16:47:03 GMT Subject: RFR: 8371309: Diagnostic.getEndPosition can throw an NPE with typical broken code In-Reply-To: References: Message-ID: On Fri, 14 Nov 2025 08:22:46 GMT, Jan Lahoda wrote: > When starting the compiler via API, a `DiagnosticListener` may be provided, to which all reported errors and warnings are reported. > > The reported diagnostics are represented by `javax.tools.Diagnostic`, which has (among others) method `getEndPosition`, which requires the end-pos-table to be set in the `DiagnosticSource` object for the given file (see `AbstractLog.sourceMap`). But the end-pos-table is only set after the parse is done: > https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L702 > > There are three problems with this: > - when a `Diagnostic` is reported by the parser, and the clients code calls `Diagnostic.getEndPosition`, the end-pos-table is not set yet, and the method crashes with an NPE > - the end-pos-table is never set for implicitly compiled (parsed) files: > https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L840 > - when a `Diagnostic` is reported for a tree by the parser, the tree on which the `Diagnostic` appear does not typically have the end position set yet - it is usually set only after the error/warning is reported > > All those problems used to be hidden by this check: > https://github.com/openjdk/jdk/blob/6c48f4ed707bf0b15f9b6098de30db8aae6fa40f/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java#L649 > but that has been removed: > https://github.com/openjdk/jdk/commit/c793de989facdb532021e1d5ddd01eb0e089b8e6 > > I have tried to fix this properly, by deferring the errors from the parser to a later point, properly setting the end-pos-table, and handling implicitly parsed files more correctly: > https://github.com/openjdk/jdk/compare/master...lahodaj:jdk:JDK-8371309b?expand=1 > but this change is a bit involved, and potentially a bit dangerous. > > So, for now, I propose to reinstate the null check in `TreeInfo.getEndPos`, to restore the JDK 25 behavior, and attempt to do the better solution later, hopefully earlier in the release cycle. It's my fault for provoking this issue with the commit you referenced - apologies, that change was overly optimistic. I agree the practical answer for now is to add back the null check. It makes me wonder if the specified behavior for `Diagnostic.getEndPosition()` was previously being adhered to. It says: > offset from beginning of file; `NOPOS` if and only if `getPosition()` returns `NOPOS` It seems like more realistic (and accurate) specification would be: > offset from beginning of file; `NOPOS` if the ending position is not available That's a separate question from this PR of course. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28316#issuecomment-3533652450 From forax at univ-mlv.fr Fri Nov 14 18:34:40 2025 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 14 Nov 2025 19:34:40 +0100 (CET) Subject: Lambda with anonymous or local class inside unnecessarily captures 'this' In-Reply-To: References: Message-ID: <1516716807.39947230.1763145280404.JavaMail.zimbra@univ-eiffel.fr> > From: "Chen Liang" > To: "Archie Cobbs" , "Tagir Valeev" > Cc: "compiler-dev" > Sent: Friday, November 14, 2025 4:15:47 PM > Subject: Re: Lambda with anonymous or local class inside unnecessarily captures > 'this' > The situation in which non-member nested classes capture the enclosing instance > unconditionally can be treated as an implementation artifact of javac; we > discussed this within Oracle a while ago. The enclosing instance capture being > the leading parameter and the null check are for linkage, but local and > anonymous classes do not have such linkage links, and it should be > JLS-compliant that unused enclosing instance capture is dropped altogether. > There are local and anonymous classes in early construction context and static > context that don't perform enclosing instance capture, yet reflectively they > are not distinguished from the ones that do, so I believe the compatibility > impact is low. > Re Archie: I think Tagir means that for 23 and below, the lambdas with local or > anonymous classes are still captured. It is interesting > withLocalClassInsideNoInstance() is suddenly deduplicated. > P.S. "Deduplication" is a confusing term - in javac I believe it refers to > identical lambda expressions reusing the same InvokeDynamic constant (which > still generates different call sites per JVMS rules), but in this thread it > refers to the singleton lambda instances. About deduplication, the term is usually used when you do not control the creation of the objects but you want later to have some sharing. In the case of javac, javac controls the objects representing the constant pool constants, so it's just sharing. > -Chen regards, R?mi > From: compiler-dev on behalf of Archie Cobbs > > Sent: Thursday, November 13, 2025 3:42 PM > To: Tagir Valeev > Cc: compiler-dev at openjdk.org > Subject: Re: Lambda with anonymous or local class inside unnecessarily captures > 'this' > Hi Tagir, > This is speculation here... > Possibly the new behavior is a side effect of [ > https://bugs.openjdk.org/browse/JDK-8164714 | > JDK-8164714 ] ( [ https://github.com/openjdk/jdk/pull/23875/files | pr #23875 ] > ) which ensures outer instances get provided as parameters, even if they are > not otherwise used, so they can be checked non-null. > I believe that parameter would later get detected by [ > https://github.com/openjdk/jdk/blob/6322aaba63b235cb6c73d23a932210af318404ec/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java#L226-L232 > | > this logic ] in InnerClassLambdaMetafactory , which would cause it to not > deduplicate the lambda instance. > If the above is true, then to fix this, one could imagine that the metafactory > logic might be made smarter, so it could filter out such "null check only" > captured outer instances. I'm not sure exactly how that would be detectable... > maybe by adding a new boolean BSM flag? > -Archie > On Thu, Nov 13, 2025 at 7:00 AM Tagir Valeev < [ mailto:amaembo at gmail.com | > amaembo at gmail.com ] > wrote: >> Hello! >> I was playing with lambda instance deduplication and come up with the following >> set of test cases: >> import java.util.function.Supplier; >> public final class CapturingLambda { >> Runnable empty() { >> return () -> {}; >> } >> Runnable simple() { >> return () -> { >> System.out.println("simple"); >> }; >> } >> Runnable withRunnableInside() { >> return () -> { >> Runnable r = () -> {}; >> r.run(); >> }; >> } >> Runnable withAnonymousRunnableInside() { >> return () -> { >> Runnable r = new Runnable() { >> @Override >> public void run() { >> } >> }; >> r.run(); >> }; >> } >> Runnable withLocalClassInside() { >> return () -> { >> class Local {} >> new Local(); >> }; >> } >> Runnable withLocalClassInsideNoInstance() { >> return () -> { >> class Local {} >> }; >> } >> void checkDeduplicated(String name, Supplier lambdaSupplier) { >> Runnable lambda1 = lambdaSupplier.get(); >> Runnable lambda2 = lambdaSupplier.get(); >> if (lambda1 == lambda2) { >> System.out.println("Deduplicated: "+name); >> } else { >> System.out.println("Not deduplicated: "+name); >> } >> } >> private void test() { >> checkDeduplicated("empty", this::empty); >> checkDeduplicated("simple", this::simple); >> checkDeduplicated("withRunnableInside", this::withRunnableInside); >> checkDeduplicated("withAnonymousRunnableInside", >> this::withAnonymousRunnableInside); >> checkDeduplicated("withLocalClassInside", this::withLocalClassInside); >> checkDeduplicated("withLocalClassInsideNoInstance", >> this::withLocalClassInsideNoInstance); >> } >> public static void main(String[] args) { >> new CapturingLambda().test(); >> } >> } >> Here, checkDeduplicated checks whether the particular lambda is deduplicated >> when returned several times. We know that lambdas are deduplicated if they >> don't capture anything. The output of this code in Java 24 and Java 25 is the >> following: >> Deduplicated: empty >> Deduplicated: simple >> Deduplicated: withRunnableInside >> Not deduplicated: withAnonymousRunnableInside >> Not deduplicated: withLocalClassInside >> Deduplicated: withLocalClassInsideNoInstance >> (side note: in Java 23 and below, withLocalClassInsideNoInstance is Not >> deduplicated) >> The problem is that lambdas returned from withAnonymousRunnableInside and >> withLocalClassInside capture 'this', thus not deduplicated. For example, here's >> the generated bytecode for withLocalClassInside: >> private void lambda$withLocalClassInside$0(); >> descriptor: ()V >> flags: (0x1002) ACC_PRIVATE, ACC_SYNTHETIC >> Code: >> stack=3, locals=1, args_size=1 >> 0: new #73 // class com/example/CapturingLambda$1Local >> 3: dup >> 4: aload_0 >> 5: invokespecial #75 // Method >> com/example/CapturingLambda$1Local."":(Lcom/example/CapturingLambda;)V >> 8: pop >> 9: return >> So 'this' is passed to the generated constructor of the local class >> CapturingLambda$1Local. However, inside the constructor, the only thing we do >> with this parameter is check it against null: >> com.example.CapturingLambda$1Local(com.example.CapturingLambda); >> descriptor: (Lcom/example/CapturingLambda;)V >> flags: (0x0000) >> Code: >> stack=2, locals=2, args_size=2 >> 0: aload_1 >> 1: dup >> 2: invokestatic #1 // Method >> java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object; >> 5: pop >> 6: pop >> 7: aload_0 >> 8: invokespecial #7 // Method java/lang/Object."":()V >> 11: return >> Is it really necessary? I understand that the mandated parameter can be probably >> helpful to maintain the (unspecified) binary compatibility with pre-Java-18 >> class files not to break the reflection code. However, can we probably omit the >> null-check and pass null here? This would help to deduplicate lambda instances >> more and remove the unnecessary strong reference to the outer object. >> Currently, the lambda cannot outlive the enclosing object, and this looks sad. >> What do you think? >> With best regards, >> Tagir Valeev > -- > Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From acobbs at openjdk.org Fri Nov 14 21:25:40 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Fri, 14 Nov 2025 21:25:40 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v5] In-Reply-To: References: Message-ID: > When bit shifting an `int` or `long` value by an amount `X`, all but the last 5 or 6 (respectively) bits of `X` are ignored. > > This can create a trap for the unwary, as in this example: > > public long readLongBigEndian(byte[] buf, int offset) { > return ((buf[offset + 0] & 0xff) << 56) // BUG HERE > | ((buf[offset + 1] & 0xff) << 48) // BUG HERE > | ((buf[offset + 2] & 0xff) << 40) // BUG HERE > | ((buf[offset + 3] & 0xff) << 32) // BUG HERE > | ((buf[offset + 4] & 0xff) << 24) > | ((buf[offset + 5] & 0xff) << 16) > | ((buf[offset + 6] & 0xff) << 8) > | ((buf[offset + 7] & 0xff); > } > > This PR adds a new warning when the compiler detects an out-of-range bit shift, i.e., an `int` bit shift not in the range `[-31...31]` or a `long` bit shift not in the range `[-63...63]`. Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: Add more verbosity to "lossy-conversions" description in @SuppressWarnings table. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27102/files - new: https://git.openjdk.org/jdk/pull/27102/files/4156e813..dc326cd3 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27102&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27102&range=03-04 Stats: 2 lines in 1 file changed: 1 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/27102.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27102/head:pull/27102 PR: https://git.openjdk.org/jdk/pull/27102 From acobbs at openjdk.org Fri Nov 14 21:37:38 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Fri, 14 Nov 2025 21:37:38 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v4] In-Reply-To: <5mFMpFFAvU3VPLU8lud1zyDDXxdILSys4MoCYoVwiZI=.8fb13cf9-8e20-4aee-9c72-5d2f0fed2ece@github.com> References: <7G0o3Ph7D9I11xzojJwIXuJ4nHvNtXtQpy2BdfuZ6Kw=.b1766068-44ad-4a74-ac51-b37b191c3e65@github.com> <5mFMpFFAvU3VPLU8lud1zyDDXxdILSys4MoCYoVwiZI=.8fb13cf9-8e20-4aee-9c72-5d2f0fed2ece@github.com> Message-ID: On Tue, 11 Nov 2025 12:40:45 GMT, Jan Lahoda wrote: >> Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: >> >> Don't warn for negative shift values that are otherwise in range. > > FWIW, from a corpus run, there are 5 cases of shift `-1`, 2 cases of shift `-5` and one cases of shift `-31`. @lahodaj, please re-review when convenient after doc-only changes requested by @jddarcy. Thanks! ------------- PR Comment: https://git.openjdk.org/jdk/pull/27102#issuecomment-3534668366 From darcy at openjdk.org Fri Nov 14 21:44:01 2025 From: darcy at openjdk.org (Joe Darcy) Date: Fri, 14 Nov 2025 21:44:01 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v5] In-Reply-To: References: Message-ID: On Fri, 14 Nov 2025 21:25:40 GMT, Archie Cobbs wrote: >> When bit shifting an `int` or `long` value by an amount `X`, all but the last 5 or 6 (respectively) bits of `X` are ignored. >> >> This can create a trap for the unwary, as in this example: >> >> public long readLongBigEndian(byte[] buf, int offset) { >> return ((buf[offset + 0] & 0xff) << 56) // BUG HERE >> | ((buf[offset + 1] & 0xff) << 48) // BUG HERE >> | ((buf[offset + 2] & 0xff) << 40) // BUG HERE >> | ((buf[offset + 3] & 0xff) << 32) // BUG HERE >> | ((buf[offset + 4] & 0xff) << 24) >> | ((buf[offset + 5] & 0xff) << 16) >> | ((buf[offset + 6] & 0xff) << 8) >> | ((buf[offset + 7] & 0xff); >> } >> >> This PR adds a new warning when the compiler detects an out-of-range bit shift, i.e., an `int` bit shift not in the range `[-31...31]` or a `long` bit shift not in the range `[-63...63]`. > > Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: > > Add more verbosity to "lossy-conversions" description in @SuppressWarnings table. Approving additional changes requested in CSR review. ------------- Marked as reviewed by darcy (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27102#pullrequestreview-3466929946 From vromero at openjdk.org Fri Nov 14 22:04:04 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 14 Nov 2025 22:04:04 GMT Subject: RFR: 8370334: javadoc NPE with "import module" statement [v2] In-Reply-To: References: Message-ID: <0jeDgji--ZZUO6tQ21WZr0MctZw0OFfAJXZiClMvy_0=.5e0e4f87-dac3-40ae-a4fc-6864b6f16811@github.com> On Mon, 3 Nov 2025 16:19:27 GMT, Jan Lahoda wrote: >> `Modules.enter` completes all root modules, but in case of additional modules being added to the module graph via `Modules.addExtraAddModules` (either from javadoc, or using the `CompilationTask.addModules`, these extra modules may not be completed at this time. Normally, they are completed eventually, but if their `module-info`s contain `import module`, an NPE will appear while checking the import, before the complete happens. >> >> The proposal herein is to consistently complete all modules in the module graph when the module graphs is setup. > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Don't eagerly complete the unnamed module. looks sensible ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27974#pullrequestreview-3466997830 From vromero at openjdk.org Fri Nov 14 22:12:00 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 14 Nov 2025 22:12:00 GMT Subject: RFR: 8371309: Diagnostic.getEndPosition can throw an NPE with typical broken code In-Reply-To: References: Message-ID: On Fri, 14 Nov 2025 08:22:46 GMT, Jan Lahoda wrote: > When starting the compiler via API, a `DiagnosticListener` may be provided, to which all reported errors and warnings are reported. > > The reported diagnostics are represented by `javax.tools.Diagnostic`, which has (among others) method `getEndPosition`, which requires the end-pos-table to be set in the `DiagnosticSource` object for the given file (see `AbstractLog.sourceMap`). But the end-pos-table is only set after the parse is done: > https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L702 > > There are three problems with this: > - when a `Diagnostic` is reported by the parser, and the clients code calls `Diagnostic.getEndPosition`, the end-pos-table is not set yet, and the method crashes with an NPE > - the end-pos-table is never set for implicitly compiled (parsed) files: > https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L840 > - when a `Diagnostic` is reported for a tree by the parser, the tree on which the `Diagnostic` appear does not typically have the end position set yet - it is usually set only after the error/warning is reported > > All those problems used to be hidden by this check: > https://github.com/openjdk/jdk/blob/6c48f4ed707bf0b15f9b6098de30db8aae6fa40f/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java#L649 > but that has been removed: > https://github.com/openjdk/jdk/commit/c793de989facdb532021e1d5ddd01eb0e089b8e6 > > I have tried to fix this properly, by deferring the errors from the parser to a later point, properly setting the end-pos-table, and handling implicitly parsed files more correctly: > https://github.com/openjdk/jdk/compare/master...lahodaj:jdk:JDK-8371309b?expand=1 > but this change is a bit involved, and potentially a bit dangerous. > > So, for now, I propose to reinstate the null check in `TreeInfo.getEndPos`, to restore the JDK 25 behavior, and attempt to do the better solution later, hopefully earlier in the release cycle. looks good ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28316#pullrequestreview-3467020088 From vromero at openjdk.org Fri Nov 14 22:17:07 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 14 Nov 2025 22:17:07 GMT Subject: RFR: 8371248: Crash in -Xdoclint with invalid @link [v4] In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 14:25:04 GMT, Jan Lahoda wrote: >> The attribution of javadoc links fails with an NPE if the link is like `{@link double.NAN Bad}` - it tries to dereference the `double`, which obviously cannot work. >> >> This PR mostly just adds checks that will stop the attribution, and return `null`. >> >> Note that for `{@link double Class}` the existing code does not crash and returns the internal a `TypeElement` corresponding to the `double`. This is a weird quirk of this API, and is preserved with this PR (although a test is added for it into `test/langtools/tools/javac/doctree/ReferenceTest.java`). > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Removing unnecessary imports as suggested. lgtm ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28272#pullrequestreview-3467035920 From vromero at openjdk.org Fri Nov 14 23:04:09 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 14 Nov 2025 23:04:09 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v9] In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 11:35:52 GMT, Jan Lahoda wrote: >> Consider this code: >> >> $ cat Test.java >> package test; >> public class Test { >> private int test1(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> case Root(R2(R2 _), R2 _) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> >> >> javac (JDK 25) will produce a compile-time error for this code: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. >> >> One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. >> >> Such path exists here (every line shows a set of patterns that is being transformed): >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ >> Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) >> Root(R2 _, R2 _) >> => >> Root _ >> => >> exhaustive >> >> >> The problem here is that in the first step, javac chooses this path: >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) >> Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) >> => dead end, as there are no two patterns that would have the same nested pattern in the same component >> >> >> If javac would do full backtracking, it could go back, and choose the other path, and find out the switch ... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Improving test reroducibility. Marked as reviewed by vromero (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27247#pullrequestreview-3467141203 From acobbs at openjdk.org Fri Nov 14 23:56:21 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Fri, 14 Nov 2025 23:56:21 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v4] In-Reply-To: <5mFMpFFAvU3VPLU8lud1zyDDXxdILSys4MoCYoVwiZI=.8fb13cf9-8e20-4aee-9c72-5d2f0fed2ece@github.com> References: <7G0o3Ph7D9I11xzojJwIXuJ4nHvNtXtQpy2BdfuZ6Kw=.b1766068-44ad-4a74-ac51-b37b191c3e65@github.com> <5mFMpFFAvU3VPLU8lud1zyDDXxdILSys4MoCYoVwiZI=.8fb13cf9-8e20-4aee-9c72-5d2f0fed2ece@github.com> Message-ID: On Tue, 11 Nov 2025 12:40:45 GMT, Jan Lahoda wrote: >> Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: >> >> Don't warn for negative shift values that are otherwise in range. > > FWIW, from a corpus run, there are 5 cases of shift `-1`, 2 cases of shift `-5` and one cases of shift `-31`. @lahodaj nevermind, @jddarcy got it! Thanks to both of you for reviewing & improving. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27102#issuecomment-3535081725 From acobbs at openjdk.org Fri Nov 14 23:56:24 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Fri, 14 Nov 2025 23:56:24 GMT Subject: Integrated: 5038439: Warning message for literal shift amounts outside the canonical domain In-Reply-To: References: Message-ID: <7qucylknrmQ6DgoDuDzgnMnzpFtS0rPuQHrStqQ87oU=.4c90f4b6-d648-4c7a-9fb8-6cd1712d869c@github.com> On Thu, 4 Sep 2025 15:22:57 GMT, Archie Cobbs wrote: > When bit shifting an `int` or `long` value by an amount `X`, all but the last 5 or 6 (respectively) bits of `X` are ignored. > > This can create a trap for the unwary, as in this example: > > public long readLongBigEndian(byte[] buf, int offset) { > return ((buf[offset + 0] & 0xff) << 56) // BUG HERE > | ((buf[offset + 1] & 0xff) << 48) // BUG HERE > | ((buf[offset + 2] & 0xff) << 40) // BUG HERE > | ((buf[offset + 3] & 0xff) << 32) // BUG HERE > | ((buf[offset + 4] & 0xff) << 24) > | ((buf[offset + 5] & 0xff) << 16) > | ((buf[offset + 6] & 0xff) << 8) > | ((buf[offset + 7] & 0xff); > } > > This PR adds a new warning when the compiler detects an out-of-range bit shift, i.e., an `int` bit shift not in the range `[-31...31]` or a `long` bit shift not in the range `[-63...63]`. This pull request has now been integrated. Changeset: bc928c81 Author: Archie Cobbs URL: https://git.openjdk.org/jdk/commit/bc928c814b5ea70505e362a643e18664e119bce3 Stats: 187 lines in 10 files changed: 183 ins; 0 del; 4 mod 5038439: Warning message for literal shift amounts outside the canonical domain Reviewed-by: darcy, jlahoda ------------- PR: https://git.openjdk.org/jdk/pull/27102 From acobbs at openjdk.org Sat Nov 15 02:57:43 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Sat, 15 Nov 2025 02:57:43 GMT Subject: RFR: 8371162: Compiler warns about implicit cast from long to int in shift operation [v3] In-Reply-To: References: Message-ID: > Consider code like this: > > int x = 1; > x <<= 1L; > > The compiler currently emits this warning: > > warning: [lossy-conversions] implicit cast from long to int in compound assignment is possibly lossy > x <<= 1L; > ^ > > By definition, bit shift operations only use the bottom 5 or 6 bits of the specified shift amount (in this example, `1L`), and the JLS does not require the shift amount to be any specific integral type, only that that it be some integral type. So as long all but the bottom 5 or 6 bits are zero, there is no loss of information and the warning is inappropriate. > > The case where the bottom 5 or 6 bits are _not_ all zero is addressed separately in [JDK-5038439](https://bugs.openjdk.org/browse/JDK-5038439). Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains three commits: - Merge branch 'master' into JDK-8371162 to fix conflict. - Use cleaner switch statement syntax. - Avoid lossy conversion warnings for 64 bit shift amounts. ------------- Changes: https://git.openjdk.org/jdk/pull/28180/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28180&range=02 Stats: 45 lines in 3 files changed: 39 ins; 4 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/28180.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28180/head:pull/28180 PR: https://git.openjdk.org/jdk/pull/28180 From pminborg at openjdk.org Sun Nov 16 09:40:19 2025 From: pminborg at openjdk.org (Per Minborg) Date: Sun, 16 Nov 2025 09:40:19 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v25] In-Reply-To: <_twwdOdK3jZMnAaDPFubJhbEbR_FEK99I4obbpttveU=.21e193fa-067e-4df1-8cff-4cd0fc704e4f@github.com> References: <_twwdOdK3jZMnAaDPFubJhbEbR_FEK99I4obbpttveU=.21e193fa-067e-4df1-8cff-4cd0fc704e4f@github.com> Message-ID: On Fri, 14 Nov 2025 09:45:39 GMT, Maurizio Cimadamore wrote: >> Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 112 commits: >> >> - Clarify toString spec >> - Merge branch 'master' into lazy-constants >> - Add @AOTSafeClassInitializer >> - Address comments in PR >> - Fix merge mistake >> - Merge master >> - Rework toString implementations >> - Update after doc comments >> - Merge branch 'master' into lazy-constants >> - Revert the AbstractMap.keySet @Stable annotation >> - ... and 102 more: https://git.openjdk.org/jdk/compare/76a1109d...1f439bec > > src/java.base/share/classes/java/lang/LazyConstant.java line 280: > >> 278: * {@code computingFunction} at least until initialization completes successfully. >> 279: *

>> 280: * If the provided computing function is already an instance of > > Not sure how I feel about that -- it seems to soft-break equals... Let's think about this once more. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2531779955 From archie.cobbs at gmail.com Sun Nov 16 18:28:15 2025 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Sun, 16 Nov 2025 12:28:15 -0600 Subject: Lambda with anonymous or local class inside unnecessarily captures 'this' In-Reply-To: References: Message-ID: Hi Chen, You're right, I had it backwards re: old vs. new behavior. Instead, I'm guessing the new (and better) behavior in the "withLocalClassInsideNoInstance" case is just a side effect of recent code refactorings. Also my speculation that the reason for the capture was due to the newly added null check was incorrect; instead, the capture was already there before. So to summarize (correct me if I'm wrong) it should be possible to eliminate the capture for local and anonymous classes when the outer instance is not actually used, and that would fix both of the remaining cases in Tagir's test ("withAnonymousRunnableInside" and "withLocalClassInside"). Thanks for clarifying! -Archie On Fri, Nov 14, 2025 at 9:15?AM Chen Liang wrote: > The situation in which non-member nested classes capture the enclosing > instance unconditionally can be treated as an implementation artifact of > javac; we discussed this within Oracle a while ago. The enclosing instance > capture being the leading parameter and the null check are for linkage, but > local and anonymous classes do not have such linkage links, and it should > be JLS-compliant that unused enclosing instance capture is dropped > altogether. There are local and anonymous classes in early construction > context and static context that don't perform enclosing instance capture, > yet reflectively they are not distinguished from the ones that do, so I > believe the compatibility impact is low. > > Re Archie: I think Tagir means that for 23 and below, the lambdas with > local or anonymous classes are still captured. It is interesting > withLocalClassInsideNoInstance() is suddenly deduplicated. > > P.S. "Deduplication" is a confusing term - in javac I believe it refers to > identical lambda expressions reusing the same InvokeDynamic constant (which > still generates different call sites per JVMS rules), but in this thread it > refers to the singleton lambda instances. > > -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From cstein at openjdk.org Mon Nov 17 07:56:35 2025 From: cstein at openjdk.org (Christian Stein) Date: Mon, 17 Nov 2025 07:56:35 GMT Subject: RFR: 8268613: jar --validate should check inital entries of a JAR file [v5] In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 08:39:37 GMT, Christian Stein wrote: >> Please review this change to include a validation check for expecting an optional JAR manifest entry being the first or second entry in JAR file. As the second entry, it must be only preceeded by an entry for the `META-INF/` directory. > > Christian Stein has updated the pull request incrementally with one additional commit since the last revision: > > Use dedicated error messages Thanks for the reviews! Tier1-3 tests look good, thus: ------------- PR Comment: https://git.openjdk.org/jdk/pull/28154#issuecomment-3540403447 From cstein at openjdk.org Mon Nov 17 07:56:36 2025 From: cstein at openjdk.org (Christian Stein) Date: Mon, 17 Nov 2025 07:56:36 GMT Subject: Integrated: 8268613: jar --validate should check inital entries of a JAR file In-Reply-To: References: Message-ID: On Wed, 5 Nov 2025 17:29:10 GMT, Christian Stein wrote: > Please review this change to include a validation check for expecting an optional JAR manifest entry being the first or second entry in JAR file. As the second entry, it must be only preceeded by an entry for the `META-INF/` directory. This pull request has now been integrated. Changeset: 8690d263 Author: Christian Stein URL: https://git.openjdk.org/jdk/commit/8690d263d9dd0fd06ed41d9529fd8cc84e1c08c8 Stats: 111 lines in 3 files changed: 111 ins; 0 del; 0 mod 8268613: jar --validate should check inital entries of a JAR file Reviewed-by: lancea, jvernee ------------- PR: https://git.openjdk.org/jdk/pull/28154 From pminborg at openjdk.org Mon Nov 17 09:32:02 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 17 Nov 2025 09:32:02 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v26] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 125 commits: - Merge branch 'master' into lazy-constants - Merge master - Fix tests and improve docs - Remove inner classes in LazyList - Fix TOC TOU issue - Improve documentation for List and Map factories - Improve doc details - Improve text for hashCode() - Refine text about reachabilit of the contents - Align doc links for get() - ... and 115 more: https://git.openjdk.org/jdk/compare/69e30244...3c26e095 ------------- Changes: https://git.openjdk.org/jdk/pull/27605/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=25 Stats: 8347 lines in 60 files changed: 3738 ins; 4490 del; 119 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From mcimadamore at openjdk.org Mon Nov 17 11:19:15 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 17 Nov 2025 11:19:15 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v26] In-Reply-To: References: Message-ID: On Mon, 17 Nov 2025 09:32:02 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 125 commits: > > - Merge branch 'master' into lazy-constants > - Merge master > - Fix tests and improve docs > - Remove inner classes in LazyList > - Fix TOC TOU issue > - Improve documentation for List and Map factories > - Improve doc details > - Improve text for hashCode() > - Refine text about reachabilit of the contents > - Align doc links for get() > - ... and 115 more: https://git.openjdk.org/jdk/compare/69e30244...3c26e095 src/java.base/share/classes/java/lang/LazyConstant.java line 244: > 242: *

> 243: * In other words, equals compares the identity of this lazy constant and {@code obj} > 244: * to determine equality. Hence, two lazy constant with the same contents are Suggestion: * to determine equality. Hence, two lazy constants with the same contents are ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2533674027 From pminborg at openjdk.org Mon Nov 17 11:29:03 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 17 Nov 2025 11:29:03 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v27] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Fix forgotten text about (List|Map)::toString ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/3c26e095..2d8f98fe Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=26 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=25-26 Stats: 10 lines in 2 files changed: 0 ins; 0 del; 10 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Mon Nov 17 11:38:03 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 17 Nov 2025 11:38:03 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v28] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Fix typo ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/2d8f98fe..e5399c5f Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=27 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=26-27 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From mcimadamore at openjdk.org Mon Nov 17 11:38:04 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 17 Nov 2025 11:38:04 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v28] In-Reply-To: References: Message-ID: On Mon, 17 Nov 2025 11:34:21 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Fix typo Great work! ------------- Marked as reviewed by mcimadamore (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27605#pullrequestreview-3472270393 From duke at openjdk.org Mon Nov 17 13:26:20 2025 From: duke at openjdk.org (David Beaumont) Date: Mon, 17 Nov 2025 13:26:20 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v28] In-Reply-To: References: Message-ID: On Mon, 17 Nov 2025 11:38:03 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Fix typo I've had a look mostly at the docs, everything I'm saying is optional (though I'd really like to see the Logger example changed). src/java.base/share/classes/java/lang/LazyConstant.java line 42: > 40: * A lazy constant is created using the factory method > 41: * {@linkplain LazyConstant#of(Supplier) LazyConstant.of({@code })}. > 42: * When created, the lazy constant is not initialized, meaning it has no contents. Subjectively, might this be clearer as a bulleted list? This is a sequence of statements about the state transitions after all.

  • On creation the lazy constant is not initialized ...
  • The first time {@linkplain #get() get()} is called ...
  • Once a lazy constant is initialized ... Or just splitting by paragraph. src/java.base/share/classes/java/lang/LazyConstant.java line 60: > 58: * private final LazyConstant logger = > 59: * // @link substring="of" target="#of" : > 60: * LazyConstant.of( () -> Logger.create(Component.class) ); We had previously talked about whether the `Logger` example is a good one. Personally I think it's a bad example if it encourages people to use loggers this way since: * non static loggers aren't suitable to logging in static methods. * The Logger framework has a perfectly functional mechanism for injecting static logger instances. * Over-use of non-static logger instances pollutes internal APIs and ends up leaking a dependency on a specific logger instance, making refactoring hard. src/java.base/share/classes/java/lang/LazyConstant.java line 66: > 64: * // ... > 65: * } > 66: * } Arguably weird/wrong indents on closing '}' ? src/java.base/share/classes/java/lang/LazyConstant.java line 241: > 239: > 240: /** > 241: * {@return if this lazy constant is the same as the provided {@code obj}} Maybe say "is the same instance as ...", then you might be able to shorten the "In other words" paragraph below as they sort of say the same thing in almost the same words. As a reader I'm more interested in *why* this slightly unexpected behaviour happens. Maybe a section in the class level docs, linked from here, explaining the issues with using the content for equals/hashCode would be better (that can also talk about lazy constants being mostly unsuitable as key types). src/java.base/share/classes/java/lang/LazyConstant.java line 283: > 281: *

    > 282: * The returned lazy constant strongly references the provided > 283: * {@code computingFunction} at least until initialization completes successfully. As a reader I'm a bit nervous that I don't know if it will ever drop the function. Suppose my init relies on something chunky I want to be sure has gone away? src/java.base/share/classes/java/nio/charset/Charset.java line 1: > 1: /* Side note: I'm slightly surprised to see the introduction and the usage happening in the same PR. Is this really being submitting in one go? src/java.base/share/classes/java/nio/charset/Charset.java line 619: > 617: > 618: private static final LazyConstant defaultCharset = LazyConstant.of( > 619: new Supplier<>() { public Charset get() { return defaultCharset0(); }}); Can these not be done with lambdas? src/java.base/share/classes/java/util/List.java line 1210: > 1208: * invoked at most once per list index, even in a multi-threaded environment. > 1209: * Competing threads accessing an element already under computation will block until > 1210: * an element is computed or the computing function completes abnormally Missing full-stop. src/java.base/share/classes/java/util/List.java line 1238: > 1236: *

    > 1237: * The returned lazy list strongly references its computing > 1238: * function used to compute elements at least so long as there are uninitialized "at least so long as" sounds weird to me. I think you would say either: * "... at least *as* long as there are uninitialized elmements." * "... so long as there are uninitialized elmements." But you could always say: * "... while there are uninitialized elements" ------------- PR Review: https://git.openjdk.org/jdk/pull/27605#pullrequestreview-3472336926 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2533786705 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2533801082 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2533773546 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2533830776 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2533836397 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2533841573 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2533846906 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2533855814 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2533865784 From pminborg at openjdk.org Mon Nov 17 13:34:30 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 17 Nov 2025 13:34:30 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v28] In-Reply-To: References: Message-ID: <6LpdzFJhGUHodyEKeOMXvKH9nYsPhz7oDM6k4NpNsNE=.2f8b7bd1-2886-48b7-9f97-22b3b8ed7368@github.com> On Mon, 17 Nov 2025 12:16:52 GMT, David Beaumont wrote: >> Per Minborg has updated the pull request incrementally with one additional commit since the last revision: >> >> Fix typo > > src/java.base/share/classes/java/nio/charset/Charset.java line 1: > >> 1: /* > > Side note: I'm slightly surprised to see the introduction and the usage happening in the same PR. Is this really being submitting in one go? I've replaced `StableValue` with `LazyConstant`. So there is no new introduction, but just an adaptation. > src/java.base/share/classes/java/nio/charset/Charset.java line 619: > >> 617: >> 618: private static final LazyConstant defaultCharset = LazyConstant.of( >> 619: new Supplier<>() { public Charset get() { return defaultCharset0(); }}); > > Can these not be done with lambdas? They can, but I wanted to keep it verbatim to the existing code. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2534085547 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2534087249 From jvernee at openjdk.org Mon Nov 17 16:52:17 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Mon, 17 Nov 2025 16:52:17 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v28] In-Reply-To: References: Message-ID: On Mon, 17 Nov 2025 11:38:03 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Fix typo test/jdk/java/lang/LazyConstant/LazyConstantTest.java line 234: > 232: return new Lazy<>(LazyConstant.of(computingFunction)); > 233: } > 234: } This appears to be unused? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2534822362 From amaembo at gmail.com Mon Nov 17 16:52:28 2025 From: amaembo at gmail.com (Tagir Valeev) Date: Mon, 17 Nov 2025 17:52:28 +0100 Subject: Lambda with anonymous or local class inside unnecessarily captures 'this' In-Reply-To: References: Message-ID: Hello! Thank you for your replies and for terminology clarification. I've created an issue based on this discussion: https://bugs.openjdk.org/browse/JDK-8372010 Feel free to edit it if it's not clearly formulated. With best regards, Tagir Valeev On Sun, Nov 16, 2025 at 7:28?PM Archie Cobbs wrote: > Hi Chen, > > You're right, I had it backwards re: old vs. new behavior. Instead, I'm > guessing the new (and better) behavior in the > "withLocalClassInsideNoInstance" case is just a side effect of recent code > refactorings. Also my speculation that the reason for the capture was due > to the newly added null check was incorrect; instead, the capture was > already there before. > > So to summarize (correct me if I'm wrong) it should be possible to > eliminate the capture for local and anonymous classes when the outer > instance is not actually used, and that would fix both of the remaining > cases in Tagir's test ("withAnonymousRunnableInside" > and "withLocalClassInside"). > > Thanks for clarifying! > > -Archie > > On Fri, Nov 14, 2025 at 9:15?AM Chen Liang > wrote: > >> The situation in which non-member nested classes capture the enclosing >> instance unconditionally can be treated as an implementation artifact of >> javac; we discussed this within Oracle a while ago. The enclosing instance >> capture being the leading parameter and the null check are for linkage, but >> local and anonymous classes do not have such linkage links, and it should >> be JLS-compliant that unused enclosing instance capture is dropped >> altogether. There are local and anonymous classes in early construction >> context and static context that don't perform enclosing instance capture, >> yet reflectively they are not distinguished from the ones that do, so I >> believe the compatibility impact is low. >> >> Re Archie: I think Tagir means that for 23 and below, the lambdas with >> local or anonymous classes are still captured. It is interesting >> withLocalClassInsideNoInstance() is suddenly deduplicated. >> >> P.S. "Deduplication" is a confusing term - in javac I believe it refers >> to identical lambda expressions reusing the same InvokeDynamic constant >> (which still generates different call sites per JVMS rules), but in this >> thread it refers to the singleton lambda instances. >> >> > > -- > Archie L. Cobbs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jvernee at openjdk.org Mon Nov 17 17:11:14 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Mon, 17 Nov 2025 17:11:14 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v28] In-Reply-To: References: Message-ID: On Mon, 17 Nov 2025 11:38:03 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Fix typo Marked as reviewed by jvernee (Reviewer). test/jdk/java/lang/LazyConstant/LazyListTest.java line 27: > 25: * @summary Basic tests for lazy list methods > 26: * @enablePreview > 27: * @run junit/othervm --add-opens java.base/java.util=ALL-UNNAMED LazyListTest I think you can do this with Suggestion: * @modules java.base/java.util:+open * @run junit LazyListTest ------------- PR Review: https://git.openjdk.org/jdk/pull/27605#pullrequestreview-3473667773 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2534826477 From jlahoda at openjdk.org Tue Nov 18 08:17:51 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 18 Nov 2025 08:17:51 GMT Subject: Integrated: 8370334: javadoc NPE with "import module" statement In-Reply-To: References: Message-ID: <83SiDS3yjQrIBf5VJTy4_v0g9t4ea9EwLbrQF5Qjb3g=.b3e69d50-fe75-4355-b749-89c19f27a0b1@github.com> On Fri, 24 Oct 2025 12:18:25 GMT, Jan Lahoda wrote: > `Modules.enter` completes all root modules, but in case of additional modules being added to the module graph via `Modules.addExtraAddModules` (either from javadoc, or using the `CompilationTask.addModules`, these extra modules may not be completed at this time. Normally, they are completed eventually, but if their `module-info`s contain `import module`, an NPE will appear while checking the import, before the complete happens. > > The proposal herein is to consistently complete all modules in the module graph when the module graphs is setup. This pull request has now been integrated. Changeset: 8af59437 Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/8af594371979b2b76ec04e0a2753413dc35b8d44 Stats: 77 lines in 3 files changed: 71 ins; 0 del; 6 mod 8370334: javadoc NPE with "import module" statement Reviewed-by: vromero ------------- PR: https://git.openjdk.org/jdk/pull/27974 From duke at openjdk.org Tue Nov 18 11:14:53 2025 From: duke at openjdk.org (ExE Boss) Date: Tue, 18 Nov 2025 11:14:53 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v28] In-Reply-To: References: Message-ID: On Mon, 17 Nov 2025 11:38:03 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Fix typo Wrt. replacing?`StableValue` with?a?`VarHandle` access?mode, that?has the?downside of?the?variable not?being constant?foldable[^1], as?the?`@Stable`?annotation is?only?available to?the?system?domain class?loaders (bootstrap?and?platform). [^1]: Without making?use of?`-Xbootclasspath/a:?`. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3547013114 From pminborg at openjdk.org Tue Nov 18 12:19:34 2025 From: pminborg at openjdk.org (Per Minborg) Date: Tue, 18 Nov 2025 12:19:34 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v28] In-Reply-To: References: Message-ID: On Mon, 17 Nov 2025 11:38:03 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Fix typo > Wrt. replacing?`StableValue` with?a?`VarHandle` access?mode, that?has the?downside of?the?variable not?being constant?foldable[1](#user-content-fn-1-dd52c5569368829688622e7b8db815eb), as?the?`@Stable`?annotation is?only?available to?the?system?domain class?loaders (bootstrap?and?platform). We think we can solve that. Stay tuned. I will integrate this PR now. There are outstanding comments in this PR that I will address in a separate follow-up PR. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3547354435 PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3547357897 From pminborg at openjdk.org Tue Nov 18 12:24:52 2025 From: pminborg at openjdk.org (Per Minborg) Date: Tue, 18 Nov 2025 12:24:52 GMT Subject: Integrated: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 10:51:08 GMT, Per Minborg wrote: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. This pull request has now been integrated. Changeset: f9464499 Author: Per Minborg URL: https://git.openjdk.org/jdk/commit/f94644999766e752f7d60ce52c14a7db79005035 Stats: 8347 lines in 60 files changed: 3738 ins; 4490 del; 119 mod 8366178: Implement JEP 526: Lazy Constants (Second Preview) 8371882: Improve documentation for JEP 526: Lazy Constants Reviewed-by: jvernee, mcimadamore ------------- PR: https://git.openjdk.org/jdk/pull/27605 From jlahoda at openjdk.org Tue Nov 18 13:58:17 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 18 Nov 2025 13:58:17 GMT Subject: Integrated: 8364991: Incorrect not-exhaustive error In-Reply-To: References: Message-ID: On Fri, 12 Sep 2025 07:53:09 GMT, Jan Lahoda wrote: > Consider this code: > > $ cat Test.java > package test; > public class Test { > private int test1(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > case Root(R2(R2 _), R2 _) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > > > javac (JDK 25) will produce a compile-time error for this code: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. > > One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. > > Such path exists here (every line shows a set of patterns that is being transformed): > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ > Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) > Root(R2 _, R2 _) > => > Root _ > => > exhaustive > > > The problem here is that in the first step, javac chooses this path: > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) > Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) > => dead end, as there are no two patterns that would have the same nested pattern in the same component > > > If javac would do full backtracking, it could go back, and choose the other path, and find out the switch is exhaustive. But, full naive backtracking is, I think, prohibitively too slow for even relatively small swit... This pull request has now been integrated. Changeset: 2e68b79a Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/2e68b79a3973c8a3dde6b47f19b19c0c7faacc51 Stats: 301 lines in 2 files changed: 260 ins; 16 del; 25 mod 8364991: Incorrect not-exhaustive error Reviewed-by: vromero ------------- PR: https://git.openjdk.org/jdk/pull/27247 From abimpoudis at openjdk.org Tue Nov 18 14:48:27 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Tue, 18 Nov 2025 14:48:27 GMT Subject: RFR: 8359145: Implement JEP 530: Primitive Types in Patterns, instanceof, and switch (Fourth Preview) [v5] In-Reply-To: References: Message-ID: > PR for Primitive Types in Patterns, instanceof, and switch (Fourth Preview). > > spec: https://cr.openjdk.org/~abimpoudis/instanceof/latest/ Aggelos Biboudis has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains eight commits: - Merge branch 'master' into JDK-8359145 - Merge branch 'master' into JDK-8359145 - Update comment - Merge branch 'master' into JDK-8359145 - Fix regression in Check - Merge branch 'master' into JDK-8359145 # Conflicts: # src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java - Address review - 8359145: JEP 530: Implement Primitive Types in Patterns, instanceof, and switch (Fourth Preview) ------------- Changes: https://git.openjdk.org/jdk/pull/27637/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27637&range=04 Stats: 774 lines in 22 files changed: 714 ins; 10 del; 50 mod Patch: https://git.openjdk.org/jdk/pull/27637.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27637/head:pull/27637 PR: https://git.openjdk.org/jdk/pull/27637 From jlahoda at openjdk.org Tue Nov 18 15:15:36 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 18 Nov 2025 15:15:36 GMT Subject: RFR: 8359145: Implement JEP 530: Primitive Types in Patterns, instanceof, and switch (Fourth Preview) [v5] In-Reply-To: References: Message-ID: On Tue, 18 Nov 2025 14:48:27 GMT, Aggelos Biboudis wrote: >> PR for Primitive Types in Patterns, instanceof, and switch (Fourth Preview). >> >> spec: https://cr.openjdk.org/~abimpoudis/instanceof/latest/ > > Aggelos Biboudis has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains eight commits: > > - Merge branch 'master' into JDK-8359145 > - Merge branch 'master' into JDK-8359145 > - Update comment > - Merge branch 'master' into JDK-8359145 > - Fix regression in Check > - Merge branch 'master' into JDK-8359145 > > # Conflicts: > # src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java > - Address review > - 8359145: JEP 530: Implement Primitive Types in Patterns, instanceof, and switch (Fourth Preview) Marked as reviewed by jlahoda (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27637#pullrequestreview-3478324526 From jlahoda at openjdk.org Tue Nov 18 15:23:38 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 18 Nov 2025 15:23:38 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v9] In-Reply-To: References: Message-ID: > Consider code like: > > package test; > public class Test { > private int test(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > ``` > > This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > The goal of this PR is to improve the error, at least in some cases to something along these lines: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > missing patterns: > test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) > 1 error > > > The (very simplified) way it works in a recursive (or induction) way: > - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. > - for a current missing pattern, try to enhance it: > - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. > - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. > > This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. > > There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. > > Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. > > There's also an open possibility for select tools to delay the more detailed computation to some later time, although that would need to be tried and eval... Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 43 commits: - Merge branch 'master' into JDK-8367530 - Fixing trailing whitespaces. - Cleanup, reflecting review feedback. - Apply suggestions from code review Co-authored-by: Aggelos Biboudis - Reflecting review comments. - Merge branch 'JDK-8364991' into JDK-8367530 - Merge branch 'master' into JDK-8364991 - Merge branch 'master' into JDK-8364991 - Fixing tests - Merge branch 'JDK-8364991-2' into JDK-8367530-2 - ... and 33 more: https://git.openjdk.org/jdk/compare/2e68b79a...3e4af725 ------------- Changes: https://git.openjdk.org/jdk/pull/27256/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=08 Stats: 1346 lines in 15 files changed: 1253 ins; 46 del; 47 mod Patch: https://git.openjdk.org/jdk/pull/27256.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27256/head:pull/27256 PR: https://git.openjdk.org/jdk/pull/27256 From jlahoda at openjdk.org Tue Nov 18 16:16:11 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 18 Nov 2025 16:16:11 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v8] In-Reply-To: References: Message-ID: On Fri, 14 Nov 2025 13:18:46 GMT, Maurizio Cimadamore wrote: >> Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: >> >> Fixing trailing whitespaces. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 939: > >> 937: removeUnnecessaryPatterns(selectorType, bp, basePatterns, inMissingPatterns, combinatorialPatterns); >> 938: >> 939: CoverageResult coverageResult = computeCoverage(targetType, combinatorialPatterns, PatternEquivalence.LOOSE); > > How can the expansion of a record pattern not cover? E.g. if we start with an exhaustive pattern `R r` and we expand `R` into all its components `R(A1, B1, C1)`, `R(A2, B2, C2)` ... -- how can we get into a situation where we're no longer exhaustive? The purpose of the code here (and a few lines below) is to merge "unnecesarily" specific patterns inside the missing patterns into their more generic supertypes. Like if at a specific place in the record patterns, there are both `A` and `B`, permitted subtypes of `Base`, we could merge and replace with `Base` here. But I understand it is somewhat matter of opinion on what is better. Note the "unnecessary" `combinatorialPatterns` (i.e. those that are covered by the user provided patterns) are already removed here, and `computeCoverage` is ran on `combinatorialPatterns`, so those may not cover the original type, because they no longer contain anything covered by the user-provided patterns. One example where this changes the outcomes is: https://github.com/openjdk/jdk/blob/da1307178912ab7bbca3ab520b44c6599cdcc1c2/test/langtools/tools/javac/patterns/ExhaustivenessConvenientErrors.java#L214 where the current outcome is: test.Test.Root(test.Test.R2 _, test.Test.Base _, test.Test.Base _) test.Test.Root(test.Test.R3 _, test.Test.Base _, test.Test.Base _) but if I disable this merging, we would get: test.Test.Root(test.Test.R3 _, test.Test.R1 _, test.Test.R2 _) test.Test.Root(test.Test.R2 _, test.Test.R1 _, test.Test.R2 _) test.Test.Root(test.Test.R2 _, test.Test.R1 _, test.Test.R3 _) test.Test.Root(test.Test.R3 _, test.Test.R2 _, test.Test.R1 _) test.Test.Root(test.Test.R3 _, test.Test.R1 _, test.Test.R1 _) test.Test.Root(test.Test.R3 _, test.Test.R2 _, test.Test.R2 _) test.Test.Root(test.Test.R3 _, test.Test.R1 _, test.Test.R3 _) test.Test.Root(test.Test.R3 _, test.Test.R3 _, test.Test.R3 _) test.Test.Root(test.Test.R2 _, test.Test.R2 _, test.Test.R3 _) test.Test.Root(test.Test.R2 _, test.Test.R3 _, test.Test.R1 _) test.Test.Root(test.Test.R3 _, test.Test.R2 _, test.Test.R3 _) test.Test.Root(test.Test.R3 _, test.Test.R3 _, test.Test.R1 _) test.Test.Root(test.Test.R3 _, test.Test.R3 _, test.Test.R2 _) test.Test.Root(test.Test.R2 _, test.Test.R1 _, test.Test.R1 _) test.Test.Root(test.Test.R2 _, test.Test.R2 _, test.Test.R2 _) test.Test.Root(test.Test.R2 _, test.Test.R2 _, test.Test.R1 _) test.Test.Root(test.Test.R2 _, test.Test.R3 _, test.Test.R2 _) test.Test.Root(test.Test.R2 _, test.Test.R3 _, test.Test.R3 _) There may be a way to better control this merging (given the original user-provided pattern has `_` on both the second and third component), but given how coverage works for record patterns, it is a bit tricky. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2538826592 From turansuleyman at proton.me Tue Nov 18 23:04:21 2025 From: turansuleyman at proton.me (Turan Suleyman) Date: Tue, 18 Nov 2025 23:04:21 +0000 Subject: [JEP Proposal] Constant-Time Enum Size Access (https://gist.github.com/TuranDev/9a20c773d8c698de918da54b2964bf65) Message-ID: Hi all, I?d like to start a discussion/gather feedback about a "small" quality of life enhancement to java.lang.Enum to add a constant-time, allocation-free way to obtain the number of constants in an enum type. Today, the usual approach is: int n = MyEnum.values().length; This creates a new array on every call, which is both non-constant time and allocates memory unnecessarily. Since the number of enum constants is fixed and known at compile time, this information could be exposed more efficiently. I?ve written a draft JEP describing two possible designs: - A compiler-generated static constant, e.g. public static final int SIZE = ; - A built-in API method such as MyEnum.size(); Draft JEP: https://gist.github.com/TuranDev/9a20c773d8c698de918da54b2964bf65 I?d appreciate feedback on: - Whether this seems like a worthwhile enhancement - Preference between the two design options - Whether anyone would be interested in sponsoring the JEP ( or rolling the change into an open piece of work) if there?s agreement to pursue it. Thank you for your time and thoughts. Best regards,Turan -------------- next part -------------- An HTML attachment was scrubbed... URL: From ron.pressler at oracle.com Tue Nov 18 23:21:55 2025 From: ron.pressler at oracle.com (Ron Pressler) Date: Tue, 18 Nov 2025 23:21:55 +0000 Subject: [JEP Proposal] Constant-Time Enum Size Access (https://gist.github.com/TuranDev/9a20c773d8c698de918da54b2964bf65) In-Reply-To: References: Message-ID: Before proposing anything, I would start with focusing on the problem. You mention allocation and performance, but not every `new X[3]` necessarily allocates anything, and even when it does, there isn?t necessarily a performance issue. Even if there is a problem, a size method or field is not necessarily the right solution. So it?s best to first identify a problem and then let the JDK maintainers come up with an appropriate solution. Do you have an example of a real program where obtaining the number of enum values makes up a significant portion of the profile and/or causes some memory-related issues? ? Ron P.S. Your document mentions ?zero-GC?, and I just want to point out that with the JDK?s more modern GCs, zero runtime allocations does not mean zero GC. In fact, allocating a new object can result in less GC work than mutating and sometimes even reading an old object. An allocation rate that?s too high can cause a lot of GC work, but so can an allocation rate that?s too low (not with the old GCs, but with the new ones). Avoiding allocations is no longer a good approach to minimising latencies in recent versions of the JDK. > On 18 Nov 2025, at 23:04, Turan Suleyman wrote: > > Hi all, > I?d like to start a discussion/gather feedback about a "small" quality of life enhancement to java.lang.Enum to add a constant-time, allocation-free way to obtain the number of constants in an enum type. > Today, the usual approach is: int n = MyEnum.values().length; > This creates a new array on every call, which is both non-constant time and allocates memory unnecessarily. > Since the number of enum constants is fixed and known at compile time, this information could be exposed more efficiently. > I?ve written a draft JEP describing two possible designs: > ? A compiler-generated static constant, e.g. > public static final int SIZE = ; > ? A built-in API method such as > MyEnum.size(); > Draft JEP: https://gist.github.com/TuranDev/9a20c773d8c698de918da54b2964bf65 > I?d appreciate feedback on: > ? Whether this seems like a worthwhile enhancement > ? Preference between the two design options > ? Whether anyone would be interested in sponsoring the JEP ( or rolling the change into an open piece of work) if there?s agreement to pursue it. > Thank you for your time and thoughts. > Best regards, > Turan From forax at univ-mlv.fr Tue Nov 18 23:40:26 2025 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 19 Nov 2025 00:40:26 +0100 (CET) Subject: [JEP Proposal] Constant-Time Enum Size Access (https://gist.github.com/TuranDev/9a20c773d8c698de918da54b2964bf65) In-Reply-To: References: Message-ID: <1864989441.42844923.1763509226118.JavaMail.zimbra@univ-eiffel.fr> What you are proposing is not backward compatible, i'm sure there are existing enum classes that declare a field named SIZE. And there is a simple solution, use an unmodifiable list. For example: enum MyEnum { public static final List VALUES = List.of(MyEnum.values()); } here, MyEnum.VALUES.size() is a constant. regards, R?mi > From: "Turan Suleyman" > To: "compiler-dev" > Sent: Wednesday, November 19, 2025 12:04:21 AM > Subject: [JEP Proposal] Constant-Time Enum Size Access > (https://gist.github.com/TuranDev/9a20c773d8c698de918da54b2964bf65) > Hi all, > I?d like to start a discussion/gather feedback about a "small" quality of life > enhancement to java.lang.Enum to add a constant-time, allocation-free way to > obtain the number of constants in an enum type. > Today, the usual approach is: int n = MyEnum.values().length; > This creates a new array on every call, which is both non-constant time and > allocates memory unnecessarily . > Since the number of enum constants is fixed and known at compile time, this > information could be exposed more efficiently. > I?ve written a draft JEP describing two possible designs: > 1. > A compiler-generated static constant , e.g. public static final int SIZE = > ; > 2. > A built-in API method such as MyEnum.size(); > Draft JEP: [ https://gist.github.com/TuranDev/9a20c773d8c698de918da54b2964bf65 | > https://gist.github.com/TuranDev/9a20c773d8c698de918da54b2964bf65 ] > I?d appreciate feedback on: > * > Whether this seems like a worthwhile enhancement > * > Preference between the two design options > * > Whether anyone would be interested in sponsoring the JEP ( or rolling the change > into an open piece of work) if there?s agreement to pursue it. > Thank you for your time and thoughts. > Best regards, > Turan -------------- next part -------------- An HTML attachment was scrubbed... URL: From abimpoudis at openjdk.org Wed Nov 19 08:51:28 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Wed, 19 Nov 2025 08:51:28 GMT Subject: Integrated: 8359145: Implement JEP 530: Primitive Types in Patterns, instanceof, and switch (Fourth Preview) In-Reply-To: References: Message-ID: On Sun, 5 Oct 2025 13:55:14 GMT, Aggelos Biboudis wrote: > PR for Primitive Types in Patterns, instanceof, and switch (Fourth Preview). > > spec: https://cr.openjdk.org/~abimpoudis/instanceof/latest/ This pull request has now been integrated. Changeset: 99135d2e Author: Aggelos Biboudis URL: https://git.openjdk.org/jdk/commit/99135d2e05bb501fe9f9f0d36abd25894d0f93de Stats: 774 lines in 22 files changed: 714 ins; 10 del; 50 mod 8359145: Implement JEP 530: Primitive Types in Patterns, instanceof, and switch (Fourth Preview) Reviewed-by: jlahoda ------------- PR: https://git.openjdk.org/jdk/pull/27637 From jlahoda at openjdk.org Wed Nov 19 08:58:30 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 19 Nov 2025 08:58:30 GMT Subject: RFR: 8371248: Crash in -Xdoclint with invalid @link [v4] In-Reply-To: References: Message-ID: On Thu, 13 Nov 2025 15:11:57 GMT, Hannes Walln?fer wrote: >> Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: >> >> Removing unnecessary imports as suggested. > > test/langtools/tools/javac/doctree/ReferenceTest.java line 111: > >> 109: * {@link java.base/java.util.Map.Entry.getKey Bad} >> 110: * {@link java.base/java.util.Map.Entry#getKey Bad} >> 111: * {@link java.base/java.util.Map.Entry#setValue(Object) Bad} > > Is there a reason parameterized types don't work with modules, or is it just an implementation quirk? Not that it matters much as it is a rather unlikely corner case. To some degree, in theory, it is only an implementation quirk. In practice, it is a bit tricky to make that work compatibly enough. I tried here: https://github.com/lahodaj/jdk/compare/JDK-8371248...lahodaj:jdk:JDK-8371248-full-attribution?expand=1 but it is not perfect. Unless there are objections, I would like to proceed with the change as it is here, and then we can see if we can improve the reference attribution. Thanks! ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28272#discussion_r2541108232 From jlahoda at openjdk.org Wed Nov 19 09:02:05 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 19 Nov 2025 09:02:05 GMT Subject: RFR: 8371309: Diagnostic.getEndPosition can throw an NPE with typical broken code [v2] In-Reply-To: References: Message-ID: > When starting the compiler via API, a `DiagnosticListener` may be provided, to which all reported errors and warnings are reported. > > The reported diagnostics are represented by `javax.tools.Diagnostic`, which has (among others) method `getEndPosition`, which requires the end-pos-table to be set in the `DiagnosticSource` object for the given file (see `AbstractLog.sourceMap`). But the end-pos-table is only set after the parse is done: > https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L702 > > There are three problems with this: > - when a `Diagnostic` is reported by the parser, and the clients code calls `Diagnostic.getEndPosition`, the end-pos-table is not set yet, and the method crashes with an NPE > - the end-pos-table is never set for implicitly compiled (parsed) files: > https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L840 > - when a `Diagnostic` is reported for a tree by the parser, the tree on which the `Diagnostic` appear does not typically have the end position set yet - it is usually set only after the error/warning is reported > > All those problems used to be hidden by this check: > https://github.com/openjdk/jdk/blob/6c48f4ed707bf0b15f9b6098de30db8aae6fa40f/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java#L649 > but that has been removed: > https://github.com/openjdk/jdk/commit/c793de989facdb532021e1d5ddd01eb0e089b8e6 > > I have tried to fix this properly, by deferring the errors from the parser to a later point, properly setting the end-pos-table, and handling implicitly parsed files more correctly: > https://github.com/openjdk/jdk/compare/master...lahodaj:jdk:JDK-8371309b?expand=1 > but this change is a bit involved, and potentially a bit dangerous. > > So, for now, I propose to reinstate the null check in `TreeInfo.getEndPos`, to restore the JDK 25 behavior, and attempt to do the better solution later, hopefully earlier in the release cycle. Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Never return NOPOS from (JCTree-based) Diagnostic's start and end position. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28316/files - new: https://git.openjdk.org/jdk/pull/28316/files/ef1f68a7..384fed72 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28316&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28316&range=00-01 Stats: 37 lines in 2 files changed: 35 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/28316.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28316/head:pull/28316 PR: https://git.openjdk.org/jdk/pull/28316 From jlahoda at openjdk.org Wed Nov 19 09:02:06 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 19 Nov 2025 09:02:06 GMT Subject: RFR: 8371309: Diagnostic.getEndPosition can throw an NPE with typical broken code In-Reply-To: References: Message-ID: On Fri, 14 Nov 2025 16:44:43 GMT, Archie Cobbs wrote: > It's my fault for provoking this issue with the commit you referenced - apologies, that change was overly optimistic. I agree the practical answer for now is to add back the null check. > > It makes me wonder if the specified behavior for `Diagnostic.getEndPosition()` was previously being adhered to. It says: > > > offset from beginning of file; `NOPOS` if and only if `getPosition()` returns `NOPOS` > > It seems like more realistic (and accurate) specification would be: > > > offset from beginning of file; `NOPOS` if the ending position is not available > > That's a separate question from this PR of course. Fixing the JCTree-based JCDiagnostics to never return NOPOS, unless the preferred position is NOPOS: https://github.com/openjdk/jdk/pull/28316/commits/384fed7243e3322495b3b4cccf13c29d1a23c0df Thanks! ------------- PR Comment: https://git.openjdk.org/jdk/pull/28316#issuecomment-3551559082 From hannesw at openjdk.org Wed Nov 19 11:37:41 2025 From: hannesw at openjdk.org (Hannes =?UTF-8?B?V2FsbG7DtmZlcg==?=) Date: Wed, 19 Nov 2025 11:37:41 GMT Subject: RFR: 8371248: Crash in -Xdoclint with invalid @link [v4] In-Reply-To: References: Message-ID: On Wed, 19 Nov 2025 08:56:08 GMT, Jan Lahoda wrote: >> test/langtools/tools/javac/doctree/ReferenceTest.java line 111: >> >>> 109: * {@link java.base/java.util.Map.Entry.getKey Bad} >>> 110: * {@link java.base/java.util.Map.Entry#getKey Bad} >>> 111: * {@link java.base/java.util.Map.Entry#setValue(Object) Bad} >> >> Is there a reason parameterized types don't work with modules, or is it just an implementation quirk? Not that it matters much as it is a rather unlikely corner case. > > To some degree, in theory, it is only an implementation quirk. In practice, it is a bit tricky to make that work compatibly enough. I tried here: > https://github.com/lahodaj/jdk/compare/JDK-8371248...lahodaj:jdk:JDK-8371248-full-attribution?expand=1 > but it is not perfect. > > Unless there are objections, I would like to proceed with the change as it is here, and then we can see if we can improve the reference attribution. > > Thanks! Thanks for the explanation, Jan. I'm fine with integrating this PR in its current form. Both module-qualified and parameterized links are so rare in real usage that this combination is not worth spending too much effort on. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28272#discussion_r2541630387 From mcimadamore at openjdk.org Wed Nov 19 12:48:26 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Wed, 19 Nov 2025 12:48:26 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v8] In-Reply-To: References: Message-ID: On Tue, 18 Nov 2025 16:13:16 GMT, Jan Lahoda wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 939: >> >>> 937: removeUnnecessaryPatterns(selectorType, bp, basePatterns, inMissingPatterns, combinatorialPatterns); >>> 938: >>> 939: CoverageResult coverageResult = computeCoverage(targetType, combinatorialPatterns, PatternEquivalence.LOOSE); >> >> How can the expansion of a record pattern not cover? E.g. if we start with an exhaustive pattern `R r` and we expand `R` into all its components `R(A1, B1, C1)`, `R(A2, B2, C2)` ... -- how can we get into a situation where we're no longer exhaustive? > > The purpose of the code here (and a few lines below) is to merge "unnecesarily" specific patterns inside the missing patterns into their more generic supertypes. Like if at a specific place in the record patterns, there are both `A` and `B`, permitted subtypes of `Base`, we could merge and replace with `Base` here. But I understand it is somewhat matter of opinion on what is better. > > Note the "unnecessary" `combinatorialPatterns` (i.e. those that are covered by the user provided patterns) are already removed here, and `computeCoverage` is ran on `combinatorialPatterns`, so those may not cover the original type, because they no longer contain anything covered by the user-provided patterns. > > One example where this changes the outcomes is: > https://github.com/openjdk/jdk/blob/da1307178912ab7bbca3ab520b44c6599cdcc1c2/test/langtools/tools/javac/patterns/ExhaustivenessConvenientErrors.java#L214 > > where the current outcome is: > > test.Test.Root(test.Test.R2 _, test.Test.Base _, test.Test.Base _) > test.Test.Root(test.Test.R3 _, test.Test.Base _, test.Test.Base _) > > > but if I disable this merging, we would get: > > test.Test.Root(test.Test.R3 _, test.Test.R1 _, test.Test.R2 _) > test.Test.Root(test.Test.R2 _, test.Test.R1 _, test.Test.R2 _) > test.Test.Root(test.Test.R2 _, test.Test.R1 _, test.Test.R3 _) > test.Test.Root(test.Test.R3 _, test.Test.R2 _, test.Test.R1 _) > test.Test.Root(test.Test.R3 _, test.Test.R1 _, test.Test.R1 _) > test.Test.Root(test.Test.R3 _, test.Test.R2 _, test.Test.R2 _) > test.Test.Root(test.Test.R3 _, test.Test.R1 _, test.Test.R3 _) > test.Test.Root(test.Test.R3 _, test.Test.R3 _, test.Test.R3 _) > test.Test.Root(test.Test.R2 _, test.Test.R2 _, test.Test.R3 _) > test.Test.Root(test.Test.R2 _, test.Test.R3 _, test.Test.R1 _) > test.Test.Root(test.Test.R3 _, test.Test.R2 _, test.Test.R3 _) > test.Test.Root(test.Test.R3 _, test.Test.R3 _, test.Test.R1 _) > test.Test.Root(test.Test.R3 _, test.Test.R3 _, test.Test.R2 _) > test.Test.Root(test.Test.R2 _, test.Test.R1 _, test.Test.R1 _) > test.Test.Root(test.Test.R2 _, test.Test.R2 _, test.Test.R2 _) > test.Test.Root(test.Test.R2 _, test.Test.R2 _, test.Test.R1 _) > test.Test.Root(test.Test.R2 _, test.Test.R3 _, test.Test.R2 _) > test.Test.Root(test.Test.R2 _, test.Test.R3 _, test.Test.R3 _) > > > There may be a way to better control this merging (given the original user-provided pattern has `_` on both the second and third component), but given how coverage works for record patterns, it is a bit tricky. Thanks, I think my question originated from a wrong assumption on how your code behaved -- after some debugging sessions I've seen cases where the set of patterns does not cover the target ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2541857235 From jlahoda at openjdk.org Wed Nov 19 16:14:23 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 19 Nov 2025 16:14:23 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v10] In-Reply-To: References: Message-ID: <4sQgry2HVxz9zmE1CFhXwluqu5LMGg6DcPHrVZ3pUhE=.e98badc2-a9ff-44fe-aaec-795eeba49c0a@github.com> > Consider code like: > > package test; > public class Test { > private int test(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > ``` > > This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > The goal of this PR is to improve the error, at least in some cases to something along these lines: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > missing patterns: > test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) > 1 error > > > The (very simplified) way it works in a recursive (or induction) way: > - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. > - for a current missing pattern, try to enhance it: > - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. > - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. > > This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. > > There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. > > Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. > > There's also an open possibility for select tools to delay the more detailed computation to some later time, although that would need to be tried and eval... Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Fixing cases that are based on review feedback. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27256/files - new: https://git.openjdk.org/jdk/pull/27256/files/3e4af725..08fdb6d9 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=09 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=08-09 Stats: 66 lines in 2 files changed: 56 ins; 0 del; 10 mod Patch: https://git.openjdk.org/jdk/pull/27256.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27256/head:pull/27256 PR: https://git.openjdk.org/jdk/pull/27256 From jlahoda at openjdk.org Wed Nov 19 16:25:08 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 19 Nov 2025 16:25:08 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v8] In-Reply-To: <8dZbRs3s5I3mI8Iwlq1NW30PJEw8huzJE9zzlCoQrS4=.5e78a559-b585-4eee-b02f-087e586b0f5c@github.com> References: <8dZbRs3s5I3mI8Iwlq1NW30PJEw8huzJE9zzlCoQrS4=.5e78a559-b585-4eee-b02f-087e586b0f5c@github.com> Message-ID: On Fri, 14 Nov 2025 13:28:29 GMT, Maurizio Cimadamore wrote: >> Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: >> >> Fixing trailing whitespaces. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 832: > >> 830: Set.of(defaultPattern)); >> 831: } catch (TimeoutException ex) { >> 832: return ex.missingPatterns != null ? ex.missingPatterns : Set.of(); > > Instead of a timeout, I wonder if you could instead cut the recursion at a specific threshold. It seems to me that recursing more will provide more precision _at the nested level_, so it's a trade off between when do we want to stop. > > Overload resolution provides some kind of precedent: > > > error: incompatible types: String cannot be converted to int > m("Hello"); > ^ > Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output > 1 error > > > (We "compress" the diagnostic whenever we can somehow figure out if an overload is "better" than the others). Then if you provide the option, you get the full thing: > > > error: no suitable method found for m(String) > m("Hello"); > ^ > method Test.m() is not applicable > (actual and formal argument lists differ in length) > method Test.m(int) is not applicable > (argument mismatch; String cannot be converted to int) > method Test.m(int,int) is not applicable > (actual and formal argument lists differ in length) > method Test.m(int,int,int) is not applicable > (actual and formal argument lists differ in length) > method Test.m(int,int,int,int) is not applicable > (actual and formal argument lists differ in length) > method Test.m(int,int,int,int,int) is not applicable > (actual and formal argument lists differ in length) > method Test.m(int,int,int,int,int,int) is not applicable > (actual and formal argument lists differ in length) > > > But, also, maybe putting an upper bound on the recursion, no matter what, might be a good idea? While I agree that having a timeout in weird/non-standard in javac, I believe it is the first time when we have a process that a) can run for a very long time; b) is not required for correctness. In all other cases I can recall, if some process is slow (including e.g. verifying exhaustiveness), then it is required for correctness. And so we cannot skip it based on criteria like time. The timeout here provides a way to say how much real-world time is the user willing to invest to get the outcome - if more time is invested, more detailed missing patterns may possibly be computed. It is a somewhat weird approach for javac, but it is a limit that (I think) the user and javac can agree on. We could introduce a limit on e.g. the depth to which we expand, but adding one level of nesting may affect performance significantly or almost not at all, depending on e.g. the record type form/shape. E.g. having a record with many components, where each component is a sealed type with many permitted subtypes, one level of nesting may lead to a high number of newly generated patterns possibly taking a lot of time to go through them. But having a record that has a single component that is not a sealed type should only generate one pattern, and so have minimal impact. > test/langtools/tools/javac/patterns/ExhaustivenessConvenientErrors.java line 290: > >> 288: case Triple(_, _, A _) -> 0; >> 289: case Triple(A p, C(Nested _, NestedBaseA _), _) -> 0; >> 290: case Triple(A p, C(Nested _, NestedBaseB _), C(Underneath _, NestedBaseA _)) -> 0; > > Where is `Underneath` defined? That's a mistake, it should be `Nested`. Fixed here: https://github.com/openjdk/jdk/pull/27256/commits/08fdb6d93ea721541a16b3e1456606dc13198136 Thanks! ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2542699544 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2542702684 From jlahoda at openjdk.org Wed Nov 19 16:48:07 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 19 Nov 2025 16:48:07 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v8] In-Reply-To: References: Message-ID: <2d4Ur2k4Fk-IBXTMgbznBsR7lV69LtEazy3ejA93mnA=.18e448bb-5d88-44da-8eb5-4f8e4d42a8fe@github.com> On Fri, 14 Nov 2025 14:14:55 GMT, Maurizio Cimadamore wrote: >> test/langtools/tools/javac/patterns/ExhaustivenessConvenientErrors.java line 352: >> >>> 350: """, >>> 351: "test.Test.Root(test.Test.R2 _, test.Test.R2(test.Test.Base _, test.Test.R2 _), test.Test.R2(test.Test.R2 _, test.Test.Base _))"); >>> 352: //ideally, the result would be as follow, but it is difficult to split Base on two distinct places: >> >> With recursion it should be possible -- but I guess the problem becomes, when do you stop? >> >> e.g. >> `{ Base } -> { R1, R2 } -> { R1, R2(Base, Base) } -> ...` > > Perhaps an idea here (not sure how crazy -- possibly a lot) would be to run an analysis on the original patterns as defined in the source code, and determine the _max depth_, and then expand "up to that depth". > > So, in the above case, you would know that when you get to `{R1, R2}`, it's "good enough" for the level of depth that is present in the code. The problem here for the current approach is that the current approach only expands one pattern at a time, but to get the optimal result here, both the `test.Test.Base _` patterns would need to be expanded at the same time (as some combinations of these two are required and some are not). I was thinking of doing a full expansion originally, but I was worried a bit that for fairly small inputs, the number of combinations could be too high. For example, a newly added: https://github.com/openjdk/jdk/blob/08fdb6d93ea721541a16b3e1456606dc13198136/test/langtools/tools/javac/patterns/ExhaustivenessConvenientErrors.java#L512 a relatively naive expansion (expanding components that have record patterns in the original pattern) would lead to a few hundreds of patterns, unless I am mistaken. There may be a way to limit the expansions, though. We can look into this deeper, surely. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2542746286 From vromero at openjdk.org Wed Nov 19 18:58:21 2025 From: vromero at openjdk.org (Vicente Romero) Date: Wed, 19 Nov 2025 18:58:21 GMT Subject: RFR: 8372023: Javac JMH failures Message-ID: <39RO_EqaChvYmUGc9pln4-2Bgkz1WBAMx4HCIN4SeEg=.354c1bb7-8d21-47b0-8444-de68f65a2e54@github.com> There are two issues here, change for [1] implied that some code that was acceptable before this change would be rejected by the compiler. This had provoked an that some JMH tests started failing. This can be fixed by compiling those cases with `-source 25`. Also while taking a look at this issue I realized that the fix for [1] had a bug which it is also being fixed here. TIA [1] https://bugs.openjdk.org/browse/JDK-8369517 ------------- Commit messages: - 8372023: Javac JMH failures Changes: https://git.openjdk.org/jdk/pull/28400/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28400&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8372023 Stats: 9 lines in 5 files changed: 5 ins; 0 del; 4 mod Patch: https://git.openjdk.org/jdk/pull/28400.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28400/head:pull/28400 PR: https://git.openjdk.org/jdk/pull/28400 From turansuleyman at proton.me Wed Nov 19 22:21:38 2025 From: turansuleyman at proton.me (Turan Suleyman) Date: Wed, 19 Nov 2025 22:21:38 +0000 Subject: [JEP Proposal] Constant-Time Enum Size Access (https://gist.github.com/TuranDev/9a20c773d8c698de918da54b2964bf65) In-Reply-To: References: Message-ID: <-fTXC4LS6p1_pkJ0DDMT1zoKYmbtSgATQZDrOKtrrgB4oLksWoeHS4qgxzfumIZiixThKTFj4Mau2lG7hJszITip4kWrvdeW48GHROpHrbw=@proton.me> Thanks both for the feedback. So to the problem. In low-latency (nanosecond sensitivity) or gc sensitive systems, it?s common for frameworks, dispatch loops, and state machines to query enum metadata on the critical path. Even small, repeated array allocations (from values()) show up as avoidable GC pressure and measurable CPU cost under load. Examples I?ve seen in practice where this occurs include: - HFT / real-time systems using enums for event codes, message categories, FIX tags - protocol engines where enums represent message types - parsers/tokenizers using enums for token types - table-driven state machines that query enum sizes on each transition Regarding the backwards compatibility comment, I understand a static SIZE field could conflict with existing code, which is why I also suggested a compiler-generated size() method. Enums already reserve compiler-generated methods like values() and valueOf(String). If a size() method were considered useful, javac would also reserve that name in the same way and emit a clear diagnostic on conflict. This would follow existing precedent. On the suggested solution of: enum MyEnum { ? public static final List VALUES = List.of(MyEnum.values()); } Yes, it?s possible to write (and myself and others already leverage such patterns or utils as workarounds) but they have to be manually added to every enum and cannot be relied on by frameworks or libraries. They?re workarounds for something the compiler knows statically. I guess to summarise the overall point of raising this is that many performance critical systems end up reinventing their own cached size patterns, suggesting (atleast in my eyes) that there is a missing language-level mechanism. Thanks again for taking the time to review this and offer guidance. Turan On Tuesday, 18 November 2025 at 23:22, Ron Pressler wrote: > Before proposing anything, I would start with focusing on the problem. > > You mention allocation and performance, but not every `new X[3]` necessarily allocates anything, and even when it does, there isn?t necessarily a performance issue. Even if there is a problem, a size method or field is not necessarily the right solution. > > So it?s best to first identify a problem and then let the JDK maintainers come up with an appropriate solution. Do you have an example of a real program where obtaining the number of enum values makes up a significant portion of the profile and/or causes some memory-related issues? > > ? Ron > > P.S. > > Your document mentions ?zero-GC?, and I just want to point out that with the JDK?s more modern GCs, zero runtime allocations does not mean zero GC. In fact, allocating a new object can result in less GC work than mutating and sometimes even reading an old object. An allocation rate that?s too high can cause a lot of GC work, but so can an allocation rate that?s too low (not with the old GCs, but with the new ones). Avoiding allocations is no longer a good approach to minimising latencies in recent versions of the JDK. > > > On 18 Nov 2025, at 23:04, Turan Suleyman turansuleyman at proton.me wrote: > > > > Hi all, > > I?d like to start a discussion/gather feedback about a "small" quality of life enhancement to java.lang.Enum to add a constant-time, allocation-free way to obtain the number of constants in an enum type. > > Today, the usual approach is: int n = MyEnum.values().length; > > This creates a new array on every call, which is both non-constant time and allocates memory unnecessarily. > > Since the number of enum constants is fixed and known at compile time, this information could be exposed more efficiently. > > I?ve written a draft JEP describing two possible designs: > > ? A compiler-generated static constant, e.g. > > public static final int SIZE = ; > > ? A built-in API method such as > > MyEnum.size(); > > Draft JEP: https://gist.github.com/TuranDev/9a20c773d8c698de918da54b2964bf65 > > I?d appreciate feedback on: > > ? Whether this seems like a worthwhile enhancement > > ? Preference between the two design options > > ? Whether anyone would be interested in sponsoring the JEP ( or rolling the change into an open piece of work) if there?s agreement to pursue it. > > Thank you for your time and thoughts. > > Best regards, > > Turan From duke at openjdk.org Thu Nov 20 04:20:48 2025 From: duke at openjdk.org (David Alayachew) Date: Thu, 20 Nov 2025 04:20:48 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v10] In-Reply-To: <4sQgry2HVxz9zmE1CFhXwluqu5LMGg6DcPHrVZ3pUhE=.e98badc2-a9ff-44fe-aaec-795eeba49c0a@github.com> References: <4sQgry2HVxz9zmE1CFhXwluqu5LMGg6DcPHrVZ3pUhE=.e98badc2-a9ff-44fe-aaec-795eeba49c0a@github.com> Message-ID: On Wed, 19 Nov 2025 16:14:23 GMT, Jan Lahoda wrote: >> Consider code like: >> >> package test; >> public class Test { >> private int test(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> ``` >> >> This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> The goal of this PR is to improve the error, at least in some cases to something along these lines: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> missing patterns: >> test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) >> 1 error >> >> >> The (very simplified) way it works in a recursive (or induction) way: >> - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. >> - for a current missing pattern, try to enhance it: >> - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. >> - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. >> >> This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. >> >> There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. >> >> Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. >> >> There's also an open possibility for select tools to... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Fixing cases that are based on review feedback. WOAH Is this fabled "Example Generator" that was talked about in the past? Does this mean that we will be granted at least one example from now on when our Switch is non-exhaustive? If so, this is amazing news! Wow! ------------- PR Comment: https://git.openjdk.org/jdk/pull/27256#issuecomment-3555689461 From jlahoda at openjdk.org Thu Nov 20 06:18:14 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 20 Nov 2025 06:18:14 GMT Subject: Integrated: 8371248: Crash in -Xdoclint with invalid @link In-Reply-To: References: Message-ID: On Wed, 12 Nov 2025 17:26:00 GMT, Jan Lahoda wrote: > The attribution of javadoc links fails with an NPE if the link is like `{@link double.NAN Bad}` - it tries to dereference the `double`, which obviously cannot work. > > This PR mostly just adds checks that will stop the attribution, and return `null`. > > Note that for `{@link double Class}` the existing code does not crash and returns the internal a `TypeElement` corresponding to the `double`. This is a weird quirk of this API, and is preserved with this PR (although a test is added for it into `test/langtools/tools/javac/doctree/ReferenceTest.java`). This pull request has now been integrated. Changeset: 5d3e73b9 Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/5d3e73b9e512b55cdf554158b19a4ec642dc1f1a Stats: 33 lines in 3 files changed: 30 ins; 0 del; 3 mod 8371248: Crash in -Xdoclint with invalid @link Reviewed-by: hannesw, vromero ------------- PR: https://git.openjdk.org/jdk/pull/28272 From jpai at openjdk.org Thu Nov 20 09:05:15 2025 From: jpai at openjdk.org (Jaikiran Pai) Date: Thu, 20 Nov 2025 09:05:15 GMT Subject: RFR: 8371470: Java Launcher does not fail when running compact java-file with private no-arg constructor [v2] In-Reply-To: References: <88t6iQiwL_FM1LOuw6-OgiGZTbVSUz95hZnlNoEpIiU=.4ad93426-b6ce-4530-813d-7e1799e1564d@github.com> Message-ID: On Thu, 13 Nov 2025 16:20:38 GMT, Christian Stein wrote: >> Please review this change to synchronize the behaviour in `java`'s source launch mode to fail when a non-arg constructor with `private` access modifier is defined - like it does in class launch mode. >> >> Find the prior-art check performed in class launch mode at [LauncherHelper.java#L958-L961](https://github.com/openjdk/jdk/blob/8102f436f5586253302cd8cef49bfe2b4af41693/src/java.base/share/classes/sun/launcher/LauncherHelper.java#L958-L961): >> >> >> Constructor constructor = mainClass.getDeclaredConstructor(); >> if (Modifier.isPrivate(constructor.getModifiers())) { >> abort(null, "java.launcher.cls.error6", className); >> } > > Christian Stein has updated the pull request incrementally with one additional commit since the last revision: > > Remove unused method This looks reasonable to me. ------------- Marked as reviewed by jpai (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28291#pullrequestreview-3486471312 From dfuchs at openjdk.org Thu Nov 20 12:26:21 2025 From: dfuchs at openjdk.org (Daniel Fuchs) Date: Thu, 20 Nov 2025 12:26:21 GMT Subject: RFR: 8372198: Avoid closing PlainHttpConnection while holding a lock [v2] In-Reply-To: References: Message-ID: > An experimental change to SelectorManager::shutdown unveil a potential deadlock between the SelectorManager thread trying to stop the HttpClientImpl, and an executor thread concurrently trying to return a connection to the pool. > > The issue seems to be caused by the ConnectionPool::returnToPool trying to close the returned connection when stopping, while holding the ConnectionPool state lock, and the SelectorManager thread trying to close a pooled connection, holding the connection stateLock and trying to close the channel, which caused the CleanupTrigger to fire and attempt to remove the connection from the pool. > > This problem was observed once with the java/net/httpclient/ThrowingSubscribersAsLimitingAsync.java test. > > To avoid the problem, the proposed fix is to wait until the ConnectionPool::stateLock has been released before actually closing the connection, and to wait until the PlainHttpConnection::stateLock has been released before actually closing the channel. Indeed, there should be no need to close those while holding the lock. Daniel Fuchs has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains two additional commits since the last revision: - Merge branch 'SelectorManagerVT-8372159' into ConnectionCloseLock-8372198 - 8372198: Avoid closing PlainHttpConnection while holding a lock ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28421/files - new: https://git.openjdk.org/jdk/pull/28421/files/177e7ee3..97ce3737 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28421&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28421&range=00-01 Stats: 19751 lines in 348 files changed: 10987 ins; 5712 del; 3052 mod Patch: https://git.openjdk.org/jdk/pull/28421.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28421/head:pull/28421 PR: https://git.openjdk.org/jdk/pull/28421 From dfuchs at openjdk.org Thu Nov 20 12:26:22 2025 From: dfuchs at openjdk.org (Daniel Fuchs) Date: Thu, 20 Nov 2025 12:26:22 GMT Subject: RFR: 8372198: Avoid closing PlainHttpConnection while holding a lock In-Reply-To: References: Message-ID: On Thu, 20 Nov 2025 10:38:08 GMT, Daniel Fuchs wrote: > An experimental change to SelectorManager::shutdown unveil a potential deadlock between the SelectorManager thread trying to stop the HttpClientImpl, and an executor thread concurrently trying to return a connection to the pool. > > The issue seems to be caused by the ConnectionPool::returnToPool trying to close the returned connection when stopping, while holding the ConnectionPool state lock, and the SelectorManager thread trying to close a pooled connection, holding the connection stateLock and trying to close the channel, which caused the CleanupTrigger to fire and attempt to remove the connection from the pool. > > This problem was observed once with the java/net/httpclient/ThrowingSubscribersAsLimitingAsync.java test. > > To avoid the problem, the proposed fix is to wait until the ConnectionPool::stateLock has been released before actually closing the connection, and to wait until the PlainHttpConnection::stateLock has been released before actually closing the channel. Indeed, there should be no need to close those while holding the lock. Something went wrong when I tried to merge the main PR branch in the dependent PR branch. I'm going to withdraw this PR and start again. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28421#issuecomment-3557752299 From dfuchs at openjdk.org Thu Nov 20 12:26:23 2025 From: dfuchs at openjdk.org (Daniel Fuchs) Date: Thu, 20 Nov 2025 12:26:23 GMT Subject: Withdrawn: 8372198: Avoid closing PlainHttpConnection while holding a lock In-Reply-To: References: Message-ID: On Thu, 20 Nov 2025 10:38:08 GMT, Daniel Fuchs wrote: > An experimental change to SelectorManager::shutdown unveil a potential deadlock between the SelectorManager thread trying to stop the HttpClientImpl, and an executor thread concurrently trying to return a connection to the pool. > > The issue seems to be caused by the ConnectionPool::returnToPool trying to close the returned connection when stopping, while holding the ConnectionPool state lock, and the SelectorManager thread trying to close a pooled connection, holding the connection stateLock and trying to close the channel, which caused the CleanupTrigger to fire and attempt to remove the connection from the pool. > > This problem was observed once with the java/net/httpclient/ThrowingSubscribersAsLimitingAsync.java test. > > To avoid the problem, the proposed fix is to wait until the ConnectionPool::stateLock has been released before actually closing the connection, and to wait until the PlainHttpConnection::stateLock has been released before actually closing the channel. Indeed, there should be no need to close those while holding the lock. This pull request has been closed without being integrated. ------------- PR: https://git.openjdk.org/jdk/pull/28421 From ron.pressler at oracle.com Thu Nov 20 13:17:18 2025 From: ron.pressler at oracle.com (Ron Pressler) Date: Thu, 20 Nov 2025 13:17:18 +0000 Subject: [External] : Re: [JEP Proposal] Constant-Time Enum Size Access (https://gist.github.com/TuranDev/9a20c773d8c698de918da54b2964bf65) In-Reply-To: <-fTXC4LS6p1_pkJ0DDMT1zoKYmbtSgATQZDrOKtrrgB4oLksWoeHS4qgxzfumIZiixThKTFj4Mau2lG7hJszITip4kWrvdeW48GHROpHrbw=@proton.me> References: <-fTXC4LS6p1_pkJ0DDMT1zoKYmbtSgATQZDrOKtrrgB4oLksWoeHS4qgxzfumIZiixThKTFj4Mau2lG7hJszITip4kWrvdeW48GHROpHrbw=@proton.me> Message-ID: > On 19 Nov 2025, at 22:21, Turan Suleyman wrote: > > Thanks both for the feedback. > > So to the problem. In low-latency (nanosecond sensitivity) or gc sensitive systems, it?s common for frameworks, dispatch loops, and state machines to query enum metadata on the critical path. > Even small, repeated array allocations (from values()) show up as avoidable GC pressure and measurable CPU cost under load. > > Examples I?ve seen in practice where this occurs include: > - HFT / real-time systems using enums for event codes, message categories, FIX tags > - protocol engines where enums represent message types > - parsers/tokenizers using enums for token types > - table-driven state machines that query enum sizes on each transition > With what JDK version and which GCs have you observed such issues? The model where allocations of short-lived objects cause more GC work isn?t the full picture with newer GCs anymore. With old GCs, fewer allocations generally meant more GC work, but these days, fewer allocations can sometimes mean *more* GC work. Also, what portion of the CPU profile or of the latency are we talking about? This is important to judge the impact of the work. After all, improving the efficiency of some operation by 10,000x would only have an impact of <0.1% if that?s the portion of the profile to begin with. > On the suggested solution of: > > enum MyEnum { > public static final List VALUES = List.of(MyEnum.values()); > } > > Yes, it?s possible to write (and myself and others already leverage such patterns or utils as workarounds) but they have to be manually added to every enum and cannot be relied on by frameworks or libraries. > They?re workarounds for something the compiler knows statically. What portion of enums are on the hot path where this has a significant impact? Also, why is the size operation in particular so common (as opposed to also looking at the values themselves)? The more we understand the problem, the better we could tailor a solution that would be maximally helpful. For example, it?s possible that the best solution isn?t in the design of enum at all, but in making sure that the JIT optimises away the allocation. ? Ron From liach at openjdk.org Thu Nov 20 14:02:31 2025 From: liach at openjdk.org (Chen Liang) Date: Thu, 20 Nov 2025 14:02:31 GMT Subject: RFR: 8372023: Javac JMH failures In-Reply-To: <39RO_EqaChvYmUGc9pln4-2Bgkz1WBAMx4HCIN4SeEg=.354c1bb7-8d21-47b0-8444-de68f65a2e54@github.com> References: <39RO_EqaChvYmUGc9pln4-2Bgkz1WBAMx4HCIN4SeEg=.354c1bb7-8d21-47b0-8444-de68f65a2e54@github.com> Message-ID: On Wed, 19 Nov 2025 18:49:15 GMT, Vicente Romero wrote: > There are two issues here, change for [1] implied that some code that was acceptable before this change would be rejected by the compiler. This had provoked an that some JMH tests started failing. This can be fixed by compiling those cases with `-source 25`. Also while taking a look at this issue I realized that the fix for [1] had a bug which it is also being fixed here. > > TIA > > [1] https://bugs.openjdk.org/browse/JDK-8369517 Marked as reviewed by liach (Reviewer). test/benchmarks/micros-javac/src/main/java/org/openjdk/bench/langtools/javac/JavacBenchmark.java line 191: > 189: } > 190: }) { > 191: String[] cmdLine = new String[] {"-source", "25", "-XDcompilePolicy=simple", "-implicit:none", "-nowarn", "--module-source-path", root.toString(), "-d", root.toString(), "-XDignore.symbol.file=true", "@" + srcList.toString()}; I recommend adding a comment in pom of this project that they need to bump the source version here if they bump the source compiled by this benchmark: https://github.com/openjdk/jdk/blob/7b11bd1b1d8dbc9bedcd8cf14e78c8f5eb06a71f/test/benchmarks/micros-javac/pom.xml#L31 ------------- PR Review: https://git.openjdk.org/jdk/pull/28400#pullrequestreview-3488018507 PR Review Comment: https://git.openjdk.org/jdk/pull/28400#discussion_r2546177328 From vromero at openjdk.org Thu Nov 20 17:03:18 2025 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 20 Nov 2025 17:03:18 GMT Subject: RFR: 8372277: Fix for JDK-8369517 is applied starting from source 24 instead of 26 Message-ID: Change for [1] had a bug, basically the code was referring to the wrong `Source.Feature` element, this is being corrected in this fix. TIA [1] https://bugs.openjdk.org/browse/JDK-8369517 ------------- Commit messages: - 8372277: Fix for JDK-8369517 is applied starting from source 24 instead of 26 Changes: https://git.openjdk.org/jdk/pull/28434/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28434&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8372277 Stats: 8 lines in 4 files changed: 5 ins; 0 del; 3 mod Patch: https://git.openjdk.org/jdk/pull/28434.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28434/head:pull/28434 PR: https://git.openjdk.org/jdk/pull/28434 From liach at openjdk.org Thu Nov 20 17:03:18 2025 From: liach at openjdk.org (Chen Liang) Date: Thu, 20 Nov 2025 17:03:18 GMT Subject: RFR: 8372277: Fix for JDK-8369517 is applied starting from source 24 instead of 26 In-Reply-To: References: Message-ID: On Thu, 20 Nov 2025 15:36:27 GMT, Vicente Romero wrote: > Change for [1] had a bug, basically the code was referring to the wrong `Source.Feature` element, this is being corrected in this fix. > > TIA > > [1] https://bugs.openjdk.org/browse/JDK-8369517 Marked as reviewed by liach (Reviewer). Bot is glitchy today ------------- PR Review: https://git.openjdk.org/jdk/pull/28434#pullrequestreview-3488525246 PR Comment: https://git.openjdk.org/jdk/pull/28434#issuecomment-3559087292 From vromero at openjdk.org Thu Nov 20 17:03:19 2025 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 20 Nov 2025 17:03:19 GMT Subject: RFR: 8372277: Fix for JDK-8369517 is applied starting from source 24 instead of 26 In-Reply-To: References: Message-ID: On Thu, 20 Nov 2025 15:38:09 GMT, Chen Liang wrote: >> Change for [1] had a bug, basically the code was referring to the wrong `Source.Feature` element, this is being corrected in this fix. >> >> TIA >> >> [1] https://bugs.openjdk.org/browse/JDK-8369517 > > Marked as reviewed by liach (Reviewer). thanks @liach for the review ------------- PR Comment: https://git.openjdk.org/jdk/pull/28434#issuecomment-3558718772 From liach at openjdk.org Thu Nov 20 17:14:27 2025 From: liach at openjdk.org (Chen Liang) Date: Thu, 20 Nov 2025 17:14:27 GMT Subject: RFR: 8372277: Fix for JDK-8369517 is applied starting from source 24 instead of 26 In-Reply-To: References: Message-ID: <4QFBG6492RFBRZazMktsqqiqD2t6a5p6GEWFGkNcI7Y=.4ba8d74c-4569-4da8-aeab-c07d74330f2a@github.com> On Thu, 20 Nov 2025 15:36:27 GMT, Vicente Romero wrote: > Change for [1] had a bug, basically the code was referring to the wrong `Source.Feature` element, this is being corrected in this fix. > > TIA > > [1] https://bugs.openjdk.org/browse/JDK-8369517 Maybe try use `8372277` as PR title and see if bot refreshes? ------------- PR Comment: https://git.openjdk.org/jdk/pull/28434#issuecomment-3559152692 From vromero at openjdk.org Thu Nov 20 17:57:43 2025 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 20 Nov 2025 17:57:43 GMT Subject: Integrated: 8372277: Fix for JDK-8369517 is applied starting from source 24 instead of 26 In-Reply-To: References: Message-ID: On Thu, 20 Nov 2025 15:36:27 GMT, Vicente Romero wrote: > Change for [1] had a bug, basically the code was referring to the wrong `Source.Feature` element, this is being corrected in this fix. > > TIA > > [1] https://bugs.openjdk.org/browse/JDK-8369517 This pull request has now been integrated. Changeset: de0a1f8f Author: Vicente Romero URL: https://git.openjdk.org/jdk/commit/de0a1f8f5191cc188800d7d06855322d272f91d6 Stats: 8 lines in 4 files changed: 5 ins; 0 del; 3 mod 8372277: Fix for JDK-8369517 is applied starting from source 24 instead of 26 Reviewed-by: liach ------------- PR: https://git.openjdk.org/jdk/pull/28434 From vromero at openjdk.org Thu Nov 20 18:17:38 2025 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 20 Nov 2025 18:17:38 GMT Subject: RFR: 8372023: Javac JMH failures [v2] In-Reply-To: <39RO_EqaChvYmUGc9pln4-2Bgkz1WBAMx4HCIN4SeEg=.354c1bb7-8d21-47b0-8444-de68f65a2e54@github.com> References: <39RO_EqaChvYmUGc9pln4-2Bgkz1WBAMx4HCIN4SeEg=.354c1bb7-8d21-47b0-8444-de68f65a2e54@github.com> Message-ID: > There are two issues here, change for [1] implied that some code that was acceptable before this change would be rejected by the compiler. This had provoked an that some JMH tests started failing. This can be fixed by compiling those cases with `-source 25`. Also while taking a look at this issue I realized that the fix for [1] had a bug which it is also being fixed here. > > TIA > > [1] https://bugs.openjdk.org/browse/JDK-8369517 Vicente Romero has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains three additional commits since the last revision: - Merge branch 'master' into JDK-8372023 - removing code from JDK-8372277 - 8372023: Javac JMH failures ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28400/files - new: https://git.openjdk.org/jdk/pull/28400/files/b50a3c83..22bc2561 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28400&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28400&range=00-01 Stats: 35444 lines in 428 files changed: 25828 ins; 7033 del; 2583 mod Patch: https://git.openjdk.org/jdk/pull/28400.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28400/head:pull/28400 PR: https://git.openjdk.org/jdk/pull/28400 From liach at openjdk.org Thu Nov 20 18:39:52 2025 From: liach at openjdk.org (Chen Liang) Date: Thu, 20 Nov 2025 18:39:52 GMT Subject: RFR: 8372023: Javac JMH failures [v3] In-Reply-To: <5gGNJER1kjqnpmVTs0r64kpEL_S2x6CRxuRMVYQC0Nc=.9a889297-6637-4998-803d-e16e9461c6ba@github.com> References: <39RO_EqaChvYmUGc9pln4-2Bgkz1WBAMx4HCIN4SeEg=.354c1bb7-8d21-47b0-8444-de68f65a2e54@github.com> <5gGNJER1kjqnpmVTs0r64kpEL_S2x6CRxuRMVYQC0Nc=.9a889297-6637-4998-803d-e16e9461c6ba@github.com> Message-ID: On Thu, 20 Nov 2025 18:35:09 GMT, Vicente Romero wrote: >> There are two issues here, change for [1] implied that some code that was acceptable before this change would be rejected by the compiler. This had provoked an that some JMH tests started failing. This can be fixed by compiling those cases with `-source 25`. Also while taking a look at this issue I realized that the fix for [1] had a bug which it is also being fixed here. >> >> TIA >> >> [1] https://bugs.openjdk.org/browse/JDK-8369517 > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > changes to pom Marked as reviewed by liach (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/28400#pullrequestreview-3489318454 From vromero at openjdk.org Thu Nov 20 18:39:51 2025 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 20 Nov 2025 18:39:51 GMT Subject: RFR: 8372023: Javac JMH failures [v3] In-Reply-To: <39RO_EqaChvYmUGc9pln4-2Bgkz1WBAMx4HCIN4SeEg=.354c1bb7-8d21-47b0-8444-de68f65a2e54@github.com> References: <39RO_EqaChvYmUGc9pln4-2Bgkz1WBAMx4HCIN4SeEg=.354c1bb7-8d21-47b0-8444-de68f65a2e54@github.com> Message-ID: <5gGNJER1kjqnpmVTs0r64kpEL_S2x6CRxuRMVYQC0Nc=.9a889297-6637-4998-803d-e16e9461c6ba@github.com> > There are two issues here, change for [1] implied that some code that was acceptable before this change would be rejected by the compiler. This had provoked an that some JMH tests started failing. This can be fixed by compiling those cases with `-source 25`. Also while taking a look at this issue I realized that the fix for [1] had a bug which it is also being fixed here. > > TIA > > [1] https://bugs.openjdk.org/browse/JDK-8369517 Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: changes to pom ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28400/files - new: https://git.openjdk.org/jdk/pull/28400/files/22bc2561..5a47f0b7 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28400&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28400&range=01-02 Stats: 6 lines in 1 file changed: 6 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/28400.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28400/head:pull/28400 PR: https://git.openjdk.org/jdk/pull/28400 From vromero at openjdk.org Thu Nov 20 18:52:26 2025 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 20 Nov 2025 18:52:26 GMT Subject: Integrated: 8372023: Javac JMH failures In-Reply-To: <39RO_EqaChvYmUGc9pln4-2Bgkz1WBAMx4HCIN4SeEg=.354c1bb7-8d21-47b0-8444-de68f65a2e54@github.com> References: <39RO_EqaChvYmUGc9pln4-2Bgkz1WBAMx4HCIN4SeEg=.354c1bb7-8d21-47b0-8444-de68f65a2e54@github.com> Message-ID: On Wed, 19 Nov 2025 18:49:15 GMT, Vicente Romero wrote: > There are two issues here, change for [1] implied that some code that was acceptable before this change would be rejected by the compiler. This had provoked an that some JMH tests started failing. This can be fixed by compiling those cases with `-source 25`. Also while taking a look at this issue I realized that the fix for [1] had a bug which it is also being fixed here. > > TIA > > [1] https://bugs.openjdk.org/browse/JDK-8369517 This pull request has now been integrated. Changeset: 0187f4df Author: Vicente Romero URL: https://git.openjdk.org/jdk/commit/0187f4df967d5b32807cfb9c1028cb75fe99b05d Stats: 7 lines in 2 files changed: 6 ins; 0 del; 1 mod 8372023: Javac JMH failures Reviewed-by: liach ------------- PR: https://git.openjdk.org/jdk/pull/28400 From vromero at openjdk.org Thu Nov 20 19:03:49 2025 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 20 Nov 2025 19:03:49 GMT Subject: RFR: 8372023: Javac JMH failures [v3] In-Reply-To: References: <39RO_EqaChvYmUGc9pln4-2Bgkz1WBAMx4HCIN4SeEg=.354c1bb7-8d21-47b0-8444-de68f65a2e54@github.com> <5gGNJER1kjqnpmVTs0r64kpEL_S2x6CRxuRMVYQC0Nc=.9a889297-6637-4998-803d-e16e9461c6ba@github.com> Message-ID: <_-GOowlyE5W7GUMiwYTQtul5nzU309hnm_MW1EK1UCA=.82bdda8c-113f-4b7b-8512-b8600ae9a17b@github.com> On Thu, 20 Nov 2025 18:33:52 GMT, Chen Liang wrote: >> Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: >> >> changes to pom > > Marked as reviewed by liach (Reviewer). thanks @liach and @asotona for the comments! ------------- PR Comment: https://git.openjdk.org/jdk/pull/28400#issuecomment-3559591484 From hannesw at openjdk.org Fri Nov 21 13:35:39 2025 From: hannesw at openjdk.org (Hannes =?UTF-8?B?V2FsbG7DtmZlcg==?=) Date: Fri, 21 Nov 2025 13:35:39 GMT Subject: RFR: 8372055: Fragment link tag does not work in package info Message-ID: Please review a change to make unqualified anchor references such as `{@link ##anchor link}` work everywhere. Previously, such links only worked in class pages. The fix consists in attributing the correct Element in `JavacTrees::attributeDocReference` for references declared in API elements, and setting it to `null` for references defined in `doc-files` to make them work as local links. Because of unattributed `doc-files` references, we also have to exclude such links from the reference check in DocLint. This is fine because local references always have a target element, and we do not check the anchor anyway. ------------- Commit messages: - Make unqualified reference in legacy package.html work as package link everywhere. - Add tests and tweak details - 8372055: Fragment link tag does not work in package info Changes: https://git.openjdk.org/jdk/pull/28372/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28372&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8372055 Stats: 156 lines in 4 files changed: 135 ins; 0 del; 21 mod Patch: https://git.openjdk.org/jdk/pull/28372.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28372/head:pull/28372 PR: https://git.openjdk.org/jdk/pull/28372 From vromero at openjdk.org Fri Nov 21 14:52:12 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 21 Nov 2025 14:52:12 GMT Subject: RFR: 8371309: Diagnostic.getEndPosition can throw an NPE with typical broken code [v2] In-Reply-To: References: Message-ID: On Wed, 19 Nov 2025 09:02:05 GMT, Jan Lahoda wrote: >> When starting the compiler via API, a `DiagnosticListener` may be provided, to which all reported errors and warnings are reported. >> >> The reported diagnostics are represented by `javax.tools.Diagnostic`, which has (among others) method `getEndPosition`, which requires the end-pos-table to be set in the `DiagnosticSource` object for the given file (see `AbstractLog.sourceMap`). But the end-pos-table is only set after the parse is done: >> https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L702 >> >> There are three problems with this: >> - when a `Diagnostic` is reported by the parser, and the clients code calls `Diagnostic.getEndPosition`, the end-pos-table is not set yet, and the method crashes with an NPE >> - the end-pos-table is never set for implicitly compiled (parsed) files: >> https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L840 >> - when a `Diagnostic` is reported for a tree by the parser, the tree on which the `Diagnostic` appear does not typically have the end position set yet - it is usually set only after the error/warning is reported >> >> All those problems used to be hidden by this check: >> https://github.com/openjdk/jdk/blob/6c48f4ed707bf0b15f9b6098de30db8aae6fa40f/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java#L649 >> but that has been removed: >> https://github.com/openjdk/jdk/commit/c793de989facdb532021e1d5ddd01eb0e089b8e6 >> >> I have tried to fix this properly, by deferring the errors from the parser to a later point, properly setting the end-pos-table, and handling implicitly parsed files more correctly: >> https://github.com/openjdk/jdk/compare/master...lahodaj:jdk:JDK-8371309b?expand=1 >> but this change is a bit involved, and potentially a bit dangerous. >> >> So, for now, I propose to reinstate the null check in `TreeInfo.getEndPos`, to restore the JDK 25 behavior, and attempt to do the better solution later, hopefully earlier in the release cycle. > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Never return NOPOS from (JCTree-based) Diagnostic's start and end position. looks good ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28316#pullrequestreview-3493077140 From ecaspole at openjdk.org Fri Nov 21 17:35:29 2025 From: ecaspole at openjdk.org (Eric Caspole) Date: Fri, 21 Nov 2025 17:35:29 GMT Subject: RFR: 8372360: Exclude jdk.jsobject from micros-javac input source packages Message-ID: It appears that somewhere in the process of [JDK-8370227](https://bugs.openjdk.org/browse/JDK-8370227) the most recent change to the micros-javac got removed, this diff needs to be reapplied to exclude jdk.jsobject. ------------- Commit messages: - 8372360: Exclude jdk.jsobject from micros-javac input source packages Changes: https://git.openjdk.org/jdk/pull/28459/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28459&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8372360 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/28459.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28459/head:pull/28459 PR: https://git.openjdk.org/jdk/pull/28459 From vromero at openjdk.org Fri Nov 21 17:35:30 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 21 Nov 2025 17:35:30 GMT Subject: RFR: 8372360: Exclude jdk.jsobject from micros-javac input source packages In-Reply-To: References: Message-ID: <2qh-G6ca1ozlmyjNcw6cSINSU0ehhvtbuo93UEPGBoQ=.7d4ab9b5-2287-4705-a619-e260c0be11c6@github.com> On Fri, 21 Nov 2025 17:26:06 GMT, Eric Caspole wrote: > It appears that somewhere in the process of [JDK-8370227](https://bugs.openjdk.org/browse/JDK-8370227) the most recent change to the micros-javac got removed, this diff needs to be reapplied to exclude jdk.jsobject. lgtm ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28459#pullrequestreview-3493744360 From ecaspole at openjdk.org Fri Nov 21 18:04:37 2025 From: ecaspole at openjdk.org (Eric Caspole) Date: Fri, 21 Nov 2025 18:04:37 GMT Subject: Integrated: 8372360: Exclude jdk.jsobject from micros-javac input source packages In-Reply-To: References: Message-ID: <4vRAoat6sOKGe8QQJIh1bUxBma9m3imPeupmfKwZg4A=.c3d4de53-4864-4216-b512-026fb24298ad@github.com> On Fri, 21 Nov 2025 17:26:06 GMT, Eric Caspole wrote: > It appears that somewhere in the process of [JDK-8370227](https://bugs.openjdk.org/browse/JDK-8370227) the most recent change to the micros-javac got removed, this diff needs to be reapplied to exclude jdk.jsobject. This pull request has now been integrated. Changeset: 5b5d85b0 Author: Eric Caspole URL: https://git.openjdk.org/jdk/commit/5b5d85b0fd4405590d69ad72474ef51fc4aa9699 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod 8372360: Exclude jdk.jsobject from micros-javac input source packages Reviewed-by: vromero ------------- PR: https://git.openjdk.org/jdk/pull/28459 From jlahoda at openjdk.org Mon Nov 24 05:59:39 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 24 Nov 2025 05:59:39 GMT Subject: Integrated: 8371309: Diagnostic.getEndPosition can throw an NPE with typical broken code In-Reply-To: References: Message-ID: On Fri, 14 Nov 2025 08:22:46 GMT, Jan Lahoda wrote: > When starting the compiler via API, a `DiagnosticListener` may be provided, to which all reported errors and warnings are reported. > > The reported diagnostics are represented by `javax.tools.Diagnostic`, which has (among others) method `getEndPosition`, which requires the end-pos-table to be set in the `DiagnosticSource` object for the given file (see `AbstractLog.sourceMap`). But the end-pos-table is only set after the parse is done: > https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L702 > > There are three problems with this: > - when a `Diagnostic` is reported by the parser, and the clients code calls `Diagnostic.getEndPosition`, the end-pos-table is not set yet, and the method crashes with an NPE > - the end-pos-table is never set for implicitly compiled (parsed) files: > https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L840 > - when a `Diagnostic` is reported for a tree by the parser, the tree on which the `Diagnostic` appear does not typically have the end position set yet - it is usually set only after the error/warning is reported > > All those problems used to be hidden by this check: > https://github.com/openjdk/jdk/blob/6c48f4ed707bf0b15f9b6098de30db8aae6fa40f/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java#L649 > but that has been removed: > https://github.com/openjdk/jdk/commit/c793de989facdb532021e1d5ddd01eb0e089b8e6 > > I have tried to fix this properly, by deferring the errors from the parser to a later point, properly setting the end-pos-table, and handling implicitly parsed files more correctly: > https://github.com/openjdk/jdk/compare/master...lahodaj:jdk:JDK-8371309b?expand=1 > but this change is a bit involved, and potentially a bit dangerous. > > So, for now, I propose to reinstate the null check in `TreeInfo.getEndPos`, to restore the JDK 25 behavior, and attempt to do the better solution later, hopefully earlier in the release cycle. This pull request has now been integrated. Changeset: 43af7b59 Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/43af7b59765fa9820726de276bae9d1fcd2ba3ca Stats: 231 lines in 3 files changed: 229 ins; 0 del; 2 mod 8371309: Diagnostic.getEndPosition can throw an NPE with typical broken code Reviewed-by: vromero ------------- PR: https://git.openjdk.org/jdk/pull/28316 From jlahoda at openjdk.org Tue Nov 25 12:29:02 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 25 Nov 2025 12:29:02 GMT Subject: RFR: 8372336: javac fails with an exception when a class is missing while evaluating conditional expression Message-ID: Consider library code like: package test; public class Intermediate extends Base {} package test; public class Base {} this is compiled, but the `Base` is missing/deleted. Now consider use of this library: package test; public class Test { private void test(Intermediate i) { int j = i != null ? i.get() : -1; } } This fails with: java.lang.NullPointerException: Cannot invoke "com.sun.tools.javac.code.Symbol.flags()" because "sym" is null at jdk.compiler/com.sun.tools.javac.code.Types.memberType(Types.java:2304) at jdk.compiler/com.sun.tools.javac.comp.Attr.isBooleanOrNumeric(Attr.java:2143) at jdk.compiler/com.sun.tools.javac.comp.Attr.isBooleanOrNumeric(Attr.java:2132) at jdk.compiler/com.sun.tools.javac.comp.Attr.visitConditional(Attr.java:2070) at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCConditional.accept(JCTree.java:1580) at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:677) ... When attributing `i.get()`, there's a `CompletionFailure` thrown, for the missing `Base`. That is OK, but in this case, the `CompletionFailure` is caught by `Attr.attribTree`, but the problem is that the AST for the method invocation does not have the `Symbol`s filled in. But `isBooleanOrNumeric` relies on a non-`null` `Symbol`: https://github.com/openjdk/jdk/blob/49176e322bbb9ed1ef2f534b949b937770b54162/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java#L2147 It would be possible to add a `null` check into `isBooleanOrNumeric`, but it seems more reliable to catch the `CompletionFailure` a bit sooner, and fill in the `Symbol` for the invocation. This is closer to what is being done in other similar cases. ------------- Commit messages: - 8372336: javac fails with an exception when a class is missing while evaluating conditional expression Changes: https://git.openjdk.org/jdk/pull/28490/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28490&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8372336 Stats: 104 lines in 2 files changed: 102 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/28490.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28490/head:pull/28490 PR: https://git.openjdk.org/jdk/pull/28490 From vromero at openjdk.org Tue Nov 25 16:10:24 2025 From: vromero at openjdk.org (Vicente Romero) Date: Tue, 25 Nov 2025 16:10:24 GMT Subject: RFR: 8372336: javac fails with an exception when a class is missing while evaluating conditional expression In-Reply-To: References: Message-ID: On Tue, 25 Nov 2025 12:21:36 GMT, Jan Lahoda wrote: > Consider library code like: > > package test; > public class Intermediate extends Base {} > package test; > public class Base {} > > > this is compiled, but the `Base` is missing/deleted. Now consider use of this library: > > package test; > public class Test { > private void test(Intermediate i) { > int j = i != null ? i.get() : -1; > } > } > > > This fails with: > > java.lang.NullPointerException: Cannot invoke "com.sun.tools.javac.code.Symbol.flags()" because "sym" is null > at jdk.compiler/com.sun.tools.javac.code.Types.memberType(Types.java:2304) > at jdk.compiler/com.sun.tools.javac.comp.Attr.isBooleanOrNumeric(Attr.java:2143) > at jdk.compiler/com.sun.tools.javac.comp.Attr.isBooleanOrNumeric(Attr.java:2132) > at jdk.compiler/com.sun.tools.javac.comp.Attr.visitConditional(Attr.java:2070) > at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCConditional.accept(JCTree.java:1580) > at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:677) > ... > > > When attributing `i.get()`, there's a `CompletionFailure` thrown, for the missing `Base`. That is OK, but in this case, the `CompletionFailure` is caught by `Attr.attribTree`, but the problem is that the AST for the method invocation does not have the `Symbol`s filled in. But `isBooleanOrNumeric` relies on a non-`null` `Symbol`: > https://github.com/openjdk/jdk/blob/49176e322bbb9ed1ef2f534b949b937770b54162/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java#L2147 > > It would be possible to add a `null` check into `isBooleanOrNumeric`, but it seems more reliable to catch the `CompletionFailure` a bit sooner, and fill in the `Symbol` for the invocation. This is closer to what is being done in other similar cases. lgtm, just a minor suggestion test/langtools/tools/javac/recovery/AttrRecovery.java line 415: > 413: """ > 414: package test; > 415: public class Base {} nit, would it make sense to actually add a `get` method to `Base`, it won't change the outcome but it will clear any confusion that the error is not related to the absence of this method ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28490#pullrequestreview-3505814323 PR Review Comment: https://git.openjdk.org/jdk/pull/28490#discussion_r2560576510 From liach at openjdk.org Tue Nov 25 17:34:40 2025 From: liach at openjdk.org (Chen Liang) Date: Tue, 25 Nov 2025 17:34:40 GMT Subject: RFR: 8372055: Fragment link tag does not work in package info In-Reply-To: References: Message-ID: On Tue, 18 Nov 2025 13:28:37 GMT, Hannes Walln?fer wrote: > Please review a change to make unqualified anchor references such as `{@link ##anchor link}` work everywhere. Previously, such links only worked in class pages. The fix consists in attributing the correct Element in `JavacTrees::attributeDocReference` for references declared in API elements, and setting it to `null` for references defined in `doc-files` to make them work as local links. > > Because of unattributed `doc-files` references, we also have to exclude such links from the reference check in DocLint. This is fine because local references always have a target element, and we do not check the anchor anyway. The tests look very good. src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java line 422: > 420: case COMPILATION_UNIT -> > 421: // Treat unqualified reference in legacy package.html as package reference. > 422: // Unqualified references in doc-fiiles only need to work locally, so null is fine. Suggestion: // Unqualified references in doc-files only need to work locally, so null is fine. src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java line 166: > 164: // Unqualified local anchor link > 165: return htmlWriter.links.createLink(HtmlId.of(refFragment), labelContent); > 166: } Why do we need a new if here? Does this not fall into the `else if (refFragment == null) {` block somehow? ------------- PR Review: https://git.openjdk.org/jdk/pull/28372#pullrequestreview-3506058261 PR Review Comment: https://git.openjdk.org/jdk/pull/28372#discussion_r2560783266 PR Review Comment: https://git.openjdk.org/jdk/pull/28372#discussion_r2560805106 From jlahoda at openjdk.org Tue Nov 25 17:37:17 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 25 Nov 2025 17:37:17 GMT Subject: RFR: 8372336: javac fails with an exception when a class is missing while evaluating conditional expression [v2] In-Reply-To: References: Message-ID: > Consider library code like: > > package test; > public class Intermediate extends Base {} > package test; > public class Base {} > > > this is compiled, but the `Base` is missing/deleted. Now consider use of this library: > > package test; > public class Test { > private void test(Intermediate i) { > int j = i != null ? i.get() : -1; > } > } > > > This fails with: > > java.lang.NullPointerException: Cannot invoke "com.sun.tools.javac.code.Symbol.flags()" because "sym" is null > at jdk.compiler/com.sun.tools.javac.code.Types.memberType(Types.java:2304) > at jdk.compiler/com.sun.tools.javac.comp.Attr.isBooleanOrNumeric(Attr.java:2143) > at jdk.compiler/com.sun.tools.javac.comp.Attr.isBooleanOrNumeric(Attr.java:2132) > at jdk.compiler/com.sun.tools.javac.comp.Attr.visitConditional(Attr.java:2070) > at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCConditional.accept(JCTree.java:1580) > at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:677) > ... > > > When attributing `i.get()`, there's a `CompletionFailure` thrown, for the missing `Base`. That is OK, but in this case, the `CompletionFailure` is caught by `Attr.attribTree`, but the problem is that the AST for the method invocation does not have the `Symbol`s filled in. But `isBooleanOrNumeric` relies on a non-`null` `Symbol`: > https://github.com/openjdk/jdk/blob/49176e322bbb9ed1ef2f534b949b937770b54162/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java#L2147 > > It would be possible to add a `null` check into `isBooleanOrNumeric`, but it seems more reliable to catch the `CompletionFailure` a bit sooner, and fill in the `Symbol` for the invocation. This is closer to what is being done in other similar cases. Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Improving test as suggested. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28490/files - new: https://git.openjdk.org/jdk/pull/28490/files/4218d5f5..83d7b253 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28490&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28490&range=00-01 Stats: 5 lines in 1 file changed: 4 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/28490.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28490/head:pull/28490 PR: https://git.openjdk.org/jdk/pull/28490 From jlahoda at openjdk.org Tue Nov 25 17:39:47 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 25 Nov 2025 17:39:47 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v11] In-Reply-To: References: Message-ID: > Consider code like: > > package test; > public class Test { > private int test(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > ``` > > This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > The goal of this PR is to improve the error, at least in some cases to something along these lines: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > missing patterns: > test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) > 1 error > > > The (very simplified) way it works in a recursive (or induction) way: > - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. > - for a current missing pattern, try to enhance it: > - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. > - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. > > This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. > > There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. > > Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. > > There's also an open possibility for select tools to delay the more detailed computation to some later time, although that would need to be tried and eval... Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 47 commits: - Fixing test. - Merge branch 'master' into JDK-8367530-3 - Reflecting review feedback: using multi-line diagnostics; passing PatternDescriptions through the diagnostics to format it at the end. - Fixing cases that are based on review feedback. - Merge branch 'master' into JDK-8367530 - Fixing trailing whitespaces. - Cleanup, reflecting review feedback. - Apply suggestions from code review Co-authored-by: Aggelos Biboudis - Reflecting review comments. - Merge branch 'JDK-8364991' into JDK-8367530 - ... and 37 more: https://git.openjdk.org/jdk/compare/81ea1442...1e6a0183 ------------- Changes: https://git.openjdk.org/jdk/pull/27256/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=10 Stats: 1453 lines in 19 files changed: 1358 ins; 45 del; 50 mod Patch: https://git.openjdk.org/jdk/pull/27256.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27256/head:pull/27256 PR: https://git.openjdk.org/jdk/pull/27256 From vromero at openjdk.org Tue Nov 25 19:27:00 2025 From: vromero at openjdk.org (Vicente Romero) Date: Tue, 25 Nov 2025 19:27:00 GMT Subject: RFR: 8372336: javac fails with an exception when a class is missing while evaluating conditional expression [v2] In-Reply-To: References: Message-ID: On Tue, 25 Nov 2025 17:37:17 GMT, Jan Lahoda wrote: >> Consider library code like: >> >> package test; >> public class Intermediate extends Base {} >> package test; >> public class Base {} >> >> >> this is compiled, but the `Base` is missing/deleted. Now consider use of this library: >> >> package test; >> public class Test { >> private void test(Intermediate i) { >> int j = i != null ? i.get() : -1; >> } >> } >> >> >> This fails with: >> >> java.lang.NullPointerException: Cannot invoke "com.sun.tools.javac.code.Symbol.flags()" because "sym" is null >> at jdk.compiler/com.sun.tools.javac.code.Types.memberType(Types.java:2304) >> at jdk.compiler/com.sun.tools.javac.comp.Attr.isBooleanOrNumeric(Attr.java:2143) >> at jdk.compiler/com.sun.tools.javac.comp.Attr.isBooleanOrNumeric(Attr.java:2132) >> at jdk.compiler/com.sun.tools.javac.comp.Attr.visitConditional(Attr.java:2070) >> at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCConditional.accept(JCTree.java:1580) >> at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:677) >> ... >> >> >> When attributing `i.get()`, there's a `CompletionFailure` thrown, for the missing `Base`. That is OK, but in this case, the `CompletionFailure` is caught by `Attr.attribTree`, but the problem is that the AST for the method invocation does not have the `Symbol`s filled in. But `isBooleanOrNumeric` relies on a non-`null` `Symbol`: >> https://github.com/openjdk/jdk/blob/49176e322bbb9ed1ef2f534b949b937770b54162/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java#L2147 >> >> It would be possible to add a `null` check into `isBooleanOrNumeric`, but it seems more reliable to catch the `CompletionFailure` a bit sooner, and fill in the `Symbol` for the invocation. This is closer to what is being done in other similar cases. > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Improving test as suggested. lgtm ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28490#pullrequestreview-3506504070 From cushon at openjdk.org Wed Nov 26 08:37:12 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 26 Nov 2025 08:37:12 GMT Subject: RFR: 8371309: Diagnostic.getEndPosition can throw an NPE with typical broken code In-Reply-To: References: Message-ID: On Wed, 19 Nov 2025 08:58:32 GMT, Jan Lahoda wrote: > It seems like more realistic (and accurate) specification would be: > > > offset from beginning of file; `NOPOS` if the ending position is not available It does seem like this changed the historic behaviour--in the past synthetic AST nodes with end position information had an end position of `NOPOS`, after this change they have an end position that is the same as their start position. I have seen some clients of this API that were checking for `endpos == NOPOS` that need to be updated to also check `endpos == pos`. (I understand this is not part of any supported API, I am not asking for a change here.) ------------- PR Comment: https://git.openjdk.org/jdk/pull/28316#issuecomment-3580117602 From hannesw at openjdk.org Wed Nov 26 09:08:43 2025 From: hannesw at openjdk.org (Hannes =?UTF-8?B?V2FsbG7DtmZlcg==?=) Date: Wed, 26 Nov 2025 09:08:43 GMT Subject: RFR: 8372055: Fragment link tag does not work in package info [v2] In-Reply-To: References: Message-ID: > Please review a change to make unqualified anchor references such as `{@link ##anchor link}` work everywhere. Previously, such links only worked in class pages. The fix consists in attributing the correct Element in `JavacTrees::attributeDocReference` for references declared in API elements, and setting it to `null` for references defined in `doc-files` to make them work as local links. > > Because of unattributed `doc-files` references, we also have to exclude such links from the reference check in DocLint. This is fine because local references always have a target element, and we do not check the anchor anyway. Hannes Walln?fer has updated the pull request incrementally with one additional commit since the last revision: Review feedback ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28372/files - new: https://git.openjdk.org/jdk/pull/28372/files/a9f5d0a2..8cf42e3e Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28372&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28372&range=00-01 Stats: 2 lines in 2 files changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/28372.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28372/head:pull/28372 PR: https://git.openjdk.org/jdk/pull/28372 From hannesw at openjdk.org Wed Nov 26 09:08:45 2025 From: hannesw at openjdk.org (Hannes =?UTF-8?B?V2FsbG7DtmZlcg==?=) Date: Wed, 26 Nov 2025 09:08:45 GMT Subject: RFR: 8372055: Fragment link tag does not work in package info [v2] In-Reply-To: References: Message-ID: On Tue, 25 Nov 2025 17:13:50 GMT, Chen Liang wrote: >> Hannes Walln?fer has updated the pull request incrementally with one additional commit since the last revision: >> >> Review feedback > > src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java line 166: > >> 164: // Unqualified local anchor link >> 165: return htmlWriter.links.createLink(HtmlId.of(refFragment), labelContent); >> 166: } > > Why do we need a new if here? Does this not fall into the `else if (refFragment == null) {` block somehow? `refFragment` is not null here, `ref` is, which is the referenced element. This is necessary for unqualified hash fragment links in doc-files, where the referenced element is set to `null` in `JavacTrees`. We know that local links in doc-files will never be used outside of the doc-file itself (for example in summary or index pages), so we can always create a simple local hash fragment link. I've updated the comment to say that this is for doc-files. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28372#discussion_r2564096439 From jlahoda at openjdk.org Wed Nov 26 10:10:00 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 26 Nov 2025 10:10:00 GMT Subject: Integrated: 8372336: javac fails with an exception when a class is missing while evaluating conditional expression In-Reply-To: References: Message-ID: On Tue, 25 Nov 2025 12:21:36 GMT, Jan Lahoda wrote: > Consider library code like: > > package test; > public class Intermediate extends Base {} > package test; > public class Base {} > > > this is compiled, but the `Base` is missing/deleted. Now consider use of this library: > > package test; > public class Test { > private void test(Intermediate i) { > int j = i != null ? i.get() : -1; > } > } > > > This fails with: > > java.lang.NullPointerException: Cannot invoke "com.sun.tools.javac.code.Symbol.flags()" because "sym" is null > at jdk.compiler/com.sun.tools.javac.code.Types.memberType(Types.java:2304) > at jdk.compiler/com.sun.tools.javac.comp.Attr.isBooleanOrNumeric(Attr.java:2143) > at jdk.compiler/com.sun.tools.javac.comp.Attr.isBooleanOrNumeric(Attr.java:2132) > at jdk.compiler/com.sun.tools.javac.comp.Attr.visitConditional(Attr.java:2070) > at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCConditional.accept(JCTree.java:1580) > at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:677) > ... > > > When attributing `i.get()`, there's a `CompletionFailure` thrown, for the missing `Base`. That is OK, but in this case, the `CompletionFailure` is caught by `Attr.attribTree`, but the problem is that the AST for the method invocation does not have the `Symbol`s filled in. But `isBooleanOrNumeric` relies on a non-`null` `Symbol`: > https://github.com/openjdk/jdk/blob/49176e322bbb9ed1ef2f534b949b937770b54162/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java#L2147 > > It would be possible to add a `null` check into `isBooleanOrNumeric`, but it seems more reliable to catch the `CompletionFailure` a bit sooner, and fill in the `Symbol` for the invocation. This is closer to what is being done in other similar cases. This pull request has now been integrated. Changeset: ac046628 Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/ac046628edaee66d1469c49864b70bdefee6570e Stats: 108 lines in 2 files changed: 106 ins; 0 del; 2 mod 8372336: javac fails with an exception when a class is missing while evaluating conditional expression Reviewed-by: vromero ------------- PR: https://git.openjdk.org/jdk/pull/28490 From cushon at google.com Wed Nov 26 13:01:43 2025 From: cushon at google.com (Liam Miller-Cushon) Date: Wed, 26 Nov 2025 14:01:43 +0100 Subject: End position storage in javac Message-ID: Hi, I wanted to discuss how javac handles end positions, and get input on the possibility of having the compiler unconditionally store end positions in a field on JCTree instead of in a separate map. Currently end position information is not stored by default, but is enabled in certain modes: if -Xjcov is set, or if the compilation includes diagnostic listeners, task listeners, or annotation processors (since they may want end positions). The hash table used to store the end positions was optimized in JDK 9 in JDK-8033287, and there was some related discussion on compiler-dev@ about the motivation for making end positions optional at that time. As I understand it, the goal is to save memory in the case where end positions aren't needed. That savings comes with a trade-off when end positions are needed, though, since the map is less efficient than storing the position directly in JCTree. Today, many invocations of javac will need end position information (annotation processing is common, when javac is used programatically in IDEs end positions will be enabled). For the invocations that do not need end positions, typical developer machines are less memory constrained than they were when the optimization for end positions was first introduced. Looking at the compilation of java.base, it contains about 3000 files and creates about 3 million AST nodes, so adding an int field to JCTree to store end positions would take about 12MB. What do you think? Would it make sense to consider adding a field to JCTree to store end positions, instead of using EndPosTable? I have a draft PR of the approach here: https://github.com/openjdk/jdk/pull/28506 Having end position information always available might enable some potential improvements to javac. For example, some compilers indicate a span of source text for some diagnostics, for example the 'range highlighting' described in these clang docs: https://clang.llvm.org/diagnostics.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From liach at openjdk.org Wed Nov 26 13:17:18 2025 From: liach at openjdk.org (Chen Liang) Date: Wed, 26 Nov 2025 13:17:18 GMT Subject: RFR: 8372055: Fragment link tag does not work in package info [v2] In-Reply-To: References: Message-ID: <1CVj16x651cmV7L5kElmp-V5QZLIBvnX9Anz12dApyg=.45aeb97b-fdfa-41c6-b3b3-091e8ff31a0c@github.com> On Wed, 26 Nov 2025 09:08:43 GMT, Hannes Walln?fer wrote: >> Please review a change to make unqualified anchor references such as `{@link ##anchor link}` work everywhere. Previously, such links only worked in class pages. The fix consists in attributing the correct Element in `JavacTrees::attributeDocReference` for references declared in API elements, and setting it to `null` for references defined in `doc-files` to make them work as local links. >> >> Because of unattributed `doc-files` references, we also have to exclude such links from the reference check in DocLint. This is fine because local references always have a target element, and we do not check the anchor anyway. > > Hannes Walln?fer has updated the pull request incrementally with one additional commit since the last revision: > > Review feedback Marked as reviewed by liach (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/28372#pullrequestreview-3510915110 From hannesw at openjdk.org Wed Nov 26 13:39:56 2025 From: hannesw at openjdk.org (Hannes =?UTF-8?B?V2FsbG7DtmZlcg==?=) Date: Wed, 26 Nov 2025 13:39:56 GMT Subject: Integrated: 8372055: Fragment link tag does not work in package info In-Reply-To: References: Message-ID: On Tue, 18 Nov 2025 13:28:37 GMT, Hannes Walln?fer wrote: > Please review a change to make unqualified anchor references such as `{@link ##anchor link}` work everywhere. Previously, such links only worked in class pages. The fix consists in attributing the correct Element in `JavacTrees::attributeDocReference` for references declared in API elements, and setting it to `null` for references defined in `doc-files` to make them work as local links. > > Because of unattributed `doc-files` references, we also have to exclude such links from the reference check in DocLint. This is fine because local references always have a target element, and we do not check the anchor anyway. This pull request has now been integrated. Changeset: 85d4f551 Author: Hannes Walln?fer URL: https://git.openjdk.org/jdk/commit/85d4f551b1f82f1b43155a4ac3c5026ac580410e Stats: 156 lines in 4 files changed: 135 ins; 0 del; 21 mod 8372055: Fragment link tag does not work in package info Reviewed-by: liach ------------- PR: https://git.openjdk.org/jdk/pull/28372 From jlahoda at openjdk.org Wed Nov 26 13:45:08 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 26 Nov 2025 13:45:08 GMT Subject: RFR: 8371309: Diagnostic.getEndPosition can throw an NPE with typical broken code [v2] In-Reply-To: References: Message-ID: On Wed, 19 Nov 2025 09:02:05 GMT, Jan Lahoda wrote: >> When starting the compiler via API, a `DiagnosticListener` may be provided, to which all reported errors and warnings are reported. >> >> The reported diagnostics are represented by `javax.tools.Diagnostic`, which has (among others) method `getEndPosition`, which requires the end-pos-table to be set in the `DiagnosticSource` object for the given file (see `AbstractLog.sourceMap`). But the end-pos-table is only set after the parse is done: >> https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L702 >> >> There are three problems with this: >> - when a `Diagnostic` is reported by the parser, and the clients code calls `Diagnostic.getEndPosition`, the end-pos-table is not set yet, and the method crashes with an NPE >> - the end-pos-table is never set for implicitly compiled (parsed) files: >> https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L840 >> - when a `Diagnostic` is reported for a tree by the parser, the tree on which the `Diagnostic` appear does not typically have the end position set yet - it is usually set only after the error/warning is reported >> >> All those problems used to be hidden by this check: >> https://github.com/openjdk/jdk/blob/6c48f4ed707bf0b15f9b6098de30db8aae6fa40f/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java#L649 >> but that has been removed: >> https://github.com/openjdk/jdk/commit/c793de989facdb532021e1d5ddd01eb0e089b8e6 >> >> I have tried to fix this properly, by deferring the errors from the parser to a later point, properly setting the end-pos-table, and handling implicitly parsed files more correctly: >> https://github.com/openjdk/jdk/compare/master...lahodaj:jdk:JDK-8371309b?expand=1 >> but this change is a bit involved, and potentially a bit dangerous. >> >> So, for now, I propose to reinstate the null check in `TreeInfo.getEndPos`, to restore the JDK 25 behavior, and attempt to do the better solution later, hopefully earlier in the release cycle. > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Never return NOPOS from (JCTree-based) Diagnostic's start and end position. Note that this was not intended to change the end pos for synthetic trees, just for diagnostics based on synthetic trees. I see there are a few calls to `JCTree.getEndPosition` in javac (some a bit misguided), but none that would immediately obviously change the outcome for synthetic trees. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28316#issuecomment-3581384009 From cushon at openjdk.org Wed Nov 26 13:58:58 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 26 Nov 2025 13:58:58 GMT Subject: RFR: 8371309: Diagnostic.getEndPosition can throw an NPE with typical broken code [v2] In-Reply-To: References: Message-ID: On Wed, 26 Nov 2025 13:42:10 GMT, Jan Lahoda wrote: > Note that this was not intended to change the end pos for synthetic trees, just for diagnostics based on synthetic trees. I see there are a few calls to `JCTree.getEndPosition` in javac (some a bit misguided), but none that would immediately obviously change the outcome for synthetic trees. Ah, OK, thanks. I filed https://bugs.openjdk.org/browse/JDK-8372611 with a repro. I don't really have concerns about either behaviour here, but it's helpful to have some way to identify synthetic AST nodes, and this broke some clients of the internal javac APIs that were checking for `endpos == NOPOS` to detect synthetic AST nodes. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28316#issuecomment-3581440002 From jlahoda at openjdk.org Wed Nov 26 14:04:04 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 26 Nov 2025 14:04:04 GMT Subject: RFR: 8371309: Diagnostic.getEndPosition can throw an NPE with typical broken code [v2] In-Reply-To: References: Message-ID: <8FL7LGsL_QmjXZhVuuJNCCdzNhTIPklu0WdyzZNLDgA=.84607700-3c8d-4268-af35-2e566651fc4e@github.com> On Wed, 19 Nov 2025 09:02:05 GMT, Jan Lahoda wrote: >> When starting the compiler via API, a `DiagnosticListener` may be provided, to which all reported errors and warnings are reported. >> >> The reported diagnostics are represented by `javax.tools.Diagnostic`, which has (among others) method `getEndPosition`, which requires the end-pos-table to be set in the `DiagnosticSource` object for the given file (see `AbstractLog.sourceMap`). But the end-pos-table is only set after the parse is done: >> https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L702 >> >> There are three problems with this: >> - when a `Diagnostic` is reported by the parser, and the clients code calls `Diagnostic.getEndPosition`, the end-pos-table is not set yet, and the method crashes with an NPE >> - the end-pos-table is never set for implicitly compiled (parsed) files: >> https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L840 >> - when a `Diagnostic` is reported for a tree by the parser, the tree on which the `Diagnostic` appear does not typically have the end position set yet - it is usually set only after the error/warning is reported >> >> All those problems used to be hidden by this check: >> https://github.com/openjdk/jdk/blob/6c48f4ed707bf0b15f9b6098de30db8aae6fa40f/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java#L649 >> but that has been removed: >> https://github.com/openjdk/jdk/commit/c793de989facdb532021e1d5ddd01eb0e089b8e6 >> >> I have tried to fix this properly, by deferring the errors from the parser to a later point, properly setting the end-pos-table, and handling implicitly parsed files more correctly: >> https://github.com/openjdk/jdk/compare/master...lahodaj:jdk:JDK-8371309b?expand=1 >> but this change is a bit involved, and potentially a bit dangerous. >> >> So, for now, I propose to reinstate the null check in `TreeInfo.getEndPos`, to restore the JDK 25 behavior, and attempt to do the better solution later, hopefully earlier in the release cycle. > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Never return NOPOS from (JCTree-based) Diagnostic's start and end position. Aha, sorry - I meant I didn't intend the outcome for trees when accessed through the API (i.e. `SourcePositions`). If you access internal methods, then anything can happen, sorry. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28316#issuecomment-3581453821 From cushon at openjdk.org Wed Nov 26 14:15:46 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 26 Nov 2025 14:15:46 GMT Subject: RFR: 8371309: Diagnostic.getEndPosition can throw an NPE with typical broken code [v2] In-Reply-To: References: Message-ID: On Wed, 19 Nov 2025 09:02:05 GMT, Jan Lahoda wrote: >> When starting the compiler via API, a `DiagnosticListener` may be provided, to which all reported errors and warnings are reported. >> >> The reported diagnostics are represented by `javax.tools.Diagnostic`, which has (among others) method `getEndPosition`, which requires the end-pos-table to be set in the `DiagnosticSource` object for the given file (see `AbstractLog.sourceMap`). But the end-pos-table is only set after the parse is done: >> https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L702 >> >> There are three problems with this: >> - when a `Diagnostic` is reported by the parser, and the clients code calls `Diagnostic.getEndPosition`, the end-pos-table is not set yet, and the method crashes with an NPE >> - the end-pos-table is never set for implicitly compiled (parsed) files: >> https://github.com/openjdk/jdk/blob/167c952bb0fefb5acc9782f4f4474d92097c93f8/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java#L840 >> - when a `Diagnostic` is reported for a tree by the parser, the tree on which the `Diagnostic` appear does not typically have the end position set yet - it is usually set only after the error/warning is reported >> >> All those problems used to be hidden by this check: >> https://github.com/openjdk/jdk/blob/6c48f4ed707bf0b15f9b6098de30db8aae6fa40f/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java#L649 >> but that has been removed: >> https://github.com/openjdk/jdk/commit/c793de989facdb532021e1d5ddd01eb0e089b8e6 >> >> I have tried to fix this properly, by deferring the errors from the parser to a later point, properly setting the end-pos-table, and handling implicitly parsed files more correctly: >> https://github.com/openjdk/jdk/compare/master...lahodaj:jdk:JDK-8371309b?expand=1 >> but this change is a bit involved, and potentially a bit dangerous. >> >> So, for now, I propose to reinstate the null check in `TreeInfo.getEndPos`, to restore the JDK 25 behavior, and attempt to do the better solution later, hopefully earlier in the release cycle. > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Never return NOPOS from (JCTree-based) Diagnostic's start and end position. Sorry, that makes sense. I see now that when using `com.sun.source.util.SourcePositions` the previous behaviour is preserved. I have closed out the bug. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28316#issuecomment-3581508455 From archie.cobbs at gmail.com Wed Nov 26 20:46:14 2025 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Wed, 26 Nov 2025 14:46:14 -0600 Subject: End position storage in javac In-Reply-To: References: Message-ID: On Wed, Nov 26, 2025 at 7:02?AM Liam Miller-Cushon wrote: > As I understand it, the goal is to save memory in the case where end > positions aren't needed. > >From what I remember, that was indeed the only counter-argument to what you're suggesting, and I'm also curious how significant the extra storage would be. Rhetorical question: if space really is so precious, then why not get rid of all the "Tag" fields and just use instanceof instead? I'm assuming the original rationale for "Tag" fields was because instanceof was too slow? If so, is that still true? What if JCTree was sealed? Perhaps such a change could be (mostly) automated, i.e., by doing this kind of transformation everywhere: --- i/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ w/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -1925,8 +1925,8 @@ private ResultInfo caseLabelResultInfo(Type seltype) { private static void addVars(List stats, WriteableScope switchScope) { for (;stats.nonEmpty(); stats = stats.tail) { JCTree stat = stats.head; - if (stat.hasTag(VARDEF)) - switchScope.enter(((JCVariableDecl) stat).sym); + if (stat instanceof JCVariableDecl varDef) + switchScope.enter(varDef.sym); } } // where -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From nbenalla at openjdk.org Thu Nov 27 00:08:17 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Thu, 27 Nov 2025 00:08:17 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 [v6] In-Reply-To: References: Message-ID: > Get JDK 27 underway. Nizar Benalla has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 12 additional commits since the last revision: - Update --release 26 symbol information for JDK 26 build 25 The macOS/AArch64 build 25 was taken from https://jdk.java.net/26/ - revert MAX_COLUMNS to 80 - Update LATEST_MAJOR_VERSION in Versions.java - Merge branch 'master' into start-of-release-27 - Merge branch 'master' into start-of-release-27 - Merge branch 'master' into start-of-release-27 - Updates due to the generate-symbol-data.sh location changing in 8367259 - Updates due to the generate-symbol-data.sh location changing in 8367259 - Merge branch 'master' into start-of-release-27 - update links to JVMS 26 and 27 - ... and 2 more: https://git.openjdk.org/jdk/compare/53a97205...78895b2b ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28130/files - new: https://git.openjdk.org/jdk/pull/28130/files/3d9eb308..78895b2b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=04-05 Stats: 69573 lines in 1019 files changed: 46890 ins; 15885 del; 6798 mod Patch: https://git.openjdk.org/jdk/pull/28130.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28130/head:pull/28130 PR: https://git.openjdk.org/jdk/pull/28130 From nbenalla at openjdk.org Thu Nov 27 00:27:50 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Thu, 27 Nov 2025 00:27:50 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 [v6] In-Reply-To: References: Message-ID: On Thu, 27 Nov 2025 00:08:17 GMT, Nizar Benalla wrote: >> Get JDK 27 underway. > > Nizar Benalla has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 12 additional commits since the last revision: > > - Update --release 26 symbol information for JDK 26 build 25 > The macOS/AArch64 build 25 was taken from https://jdk.java.net/26/ > - revert MAX_COLUMNS to 80 > - Update LATEST_MAJOR_VERSION in Versions.java > - Merge branch 'master' into start-of-release-27 > - Merge branch 'master' into start-of-release-27 > - Merge branch 'master' into start-of-release-27 > - Updates due to the generate-symbol-data.sh location changing in 8367259 > - Updates due to the generate-symbol-data.sh location changing in 8367259 > - Merge branch 'master' into start-of-release-27 > - update links to JVMS 26 and 27 > - ... and 2 more: https://git.openjdk.org/jdk/compare/4bfba094...78895b2b I had to make some changes to respect the 80 character limit we used to have. Instead of showing a long list for the --release values in the javac help output we show the following: --target , -target Generate class files suitable for the specified Java SE release. Supported releases: 8, 9, 10, ..., 25, 26, 27 ------------- PR Comment: https://git.openjdk.org/jdk/pull/28130#issuecomment-3583630744 From iris at openjdk.org Thu Nov 27 00:37:53 2025 From: iris at openjdk.org (Iris Clark) Date: Thu, 27 Nov 2025 00:37:53 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 [v6] In-Reply-To: References: Message-ID: <97FR4fTVW5KDQNoJ16P5pFYEvuMdhM3OjTX9lZF1xLo=.5a78ad27-3de5-46f7-818c-a3c14a0cb4a1@github.com> On Thu, 27 Nov 2025 00:08:17 GMT, Nizar Benalla wrote: >> Get JDK 27 underway. > > Nizar Benalla has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 12 additional commits since the last revision: > > - Update --release 26 symbol information for JDK 26 build 25 > The macOS/AArch64 build 25 was taken from https://jdk.java.net/26/ > - revert MAX_COLUMNS to 80 > - Update LATEST_MAJOR_VERSION in Versions.java > - Merge branch 'master' into start-of-release-27 > - Merge branch 'master' into start-of-release-27 > - Merge branch 'master' into start-of-release-27 > - Updates due to the generate-symbol-data.sh location changing in 8367259 > - Updates due to the generate-symbol-data.sh location changing in 8367259 > - Merge branch 'master' into start-of-release-27 > - update links to JVMS 26 and 27 > - ... and 2 more: https://git.openjdk.org/jdk/compare/a52f9076...78895b2b The changes in com.sun.tools.javac.main.Option don't appear strictly necessary for the start of release updates... test/langtools/tools/javac/options/HelpOutputColumnWidthTest.java line 50: > 48: public class HelpOutputColumnWidthTest extends TestRunner { > 49: > 50: public static final int MAX_COLUMNS = 80; I though that the default terminal width was 24x80 in most systems, so 84 seems an odd choice. I agree that 80 seems more appropriate. ------------- PR Review: https://git.openjdk.org/jdk/pull/28130#pullrequestreview-3513096801 PR Review Comment: https://git.openjdk.org/jdk/pull/28130#discussion_r2566785560 From iris at openjdk.org Thu Nov 27 00:37:54 2025 From: iris at openjdk.org (Iris Clark) Date: Thu, 27 Nov 2025 00:37:54 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 [v6] In-Reply-To: <97FR4fTVW5KDQNoJ16P5pFYEvuMdhM3OjTX9lZF1xLo=.5a78ad27-3de5-46f7-818c-a3c14a0cb4a1@github.com> References: <97FR4fTVW5KDQNoJ16P5pFYEvuMdhM3OjTX9lZF1xLo=.5a78ad27-3de5-46f7-818c-a3c14a0cb4a1@github.com> Message-ID: On Thu, 27 Nov 2025 00:31:23 GMT, Iris Clark wrote: >> Nizar Benalla has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 12 additional commits since the last revision: >> >> - Update --release 26 symbol information for JDK 26 build 25 >> The macOS/AArch64 build 25 was taken from https://jdk.java.net/26/ >> - revert MAX_COLUMNS to 80 >> - Update LATEST_MAJOR_VERSION in Versions.java >> - Merge branch 'master' into start-of-release-27 >> - Merge branch 'master' into start-of-release-27 >> - Merge branch 'master' into start-of-release-27 >> - Updates due to the generate-symbol-data.sh location changing in 8367259 >> - Updates due to the generate-symbol-data.sh location changing in 8367259 >> - Merge branch 'master' into start-of-release-27 >> - update links to JVMS 26 and 27 >> - ... and 2 more: https://git.openjdk.org/jdk/compare/a52f9076...78895b2b > > test/langtools/tools/javac/options/HelpOutputColumnWidthTest.java line 50: > >> 48: public class HelpOutputColumnWidthTest extends TestRunner { >> 49: >> 50: public static final int MAX_COLUMNS = 80; > > I though that the default terminal width was 24x80 in most systems, so 84 seems an odd choice. I agree that 80 seems more appropriate. oops.. that should have been `80x24`. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28130#discussion_r2566789434 From nbenalla at openjdk.org Thu Nov 27 02:25:47 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Thu, 27 Nov 2025 02:25:47 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 [v6] In-Reply-To: References: <97FR4fTVW5KDQNoJ16P5pFYEvuMdhM3OjTX9lZF1xLo=.5a78ad27-3de5-46f7-818c-a3c14a0cb4a1@github.com> Message-ID: On Thu, 27 Nov 2025 00:35:11 GMT, Iris Clark wrote: >> test/langtools/tools/javac/options/HelpOutputColumnWidthTest.java line 50: >> >>> 48: public class HelpOutputColumnWidthTest extends TestRunner { >>> 49: >>> 50: public static final int MAX_COLUMNS = 80; >> >> I though that the default terminal width was 24x80 in most systems, so 84 seems an odd choice. I agree that 80 seems more appropriate. > > oops.. that should have been `80x24`. I should have included more [context](https://github.com/openjdk/jdk/pull/25008#discussion_r2071880549). The default width was increased to 84 in the last start of release update, I reverted it back to the original value. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28130#discussion_r2566979887 From maurizio.cimadamore at oracle.com Thu Nov 27 13:45:56 2025 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 27 Nov 2025 13:45:56 +0000 Subject: End position storage in javac In-Reply-To: References: Message-ID: <1e9cec1e-eb8d-4745-86ef-ebc0c1c6f5fc@oracle.com> Hi Liam, Archie I believe this came up also in the recent discussions on lint warnings, where we needed to expand the set of end positions retained by default. I think the long term solution here is, as you say (and I think Jan supports that too) that end positions should be just stored by default in the trees. There's a lot of things javac does "its own way" for reasons sometimes good, sometimes less good. For instance, javac had to use its own `List` because when it was written generics were not yet available. That said, one issue with using just a plain j.l.List (like ArrayList) in javac is that (a) javac typically operates on very small lists, where the overhead of array lists might be too big and (b) j.u.List is very bad for recursing algorithms, which is what javac is all about. So, I believe using a custom List impl there seems to be a good trade off. Other areas that are brought up from time to time are: * use of special data structures for scopes -- why not just maps? * use of special data structures for names -- why not just strings? I believe we did some experiments on the former, and concluded that javac implementation was still better than a hashmap (as javac requirement are specialized, and scopes need to be traversed in different ways, and somtimes a new scope needs to be "pushed" on top of an old one -- reusing the undelrying entries). For names I'm less sure, but maybe somebody else knows the answer there. Then there's the general lack of data-orientedness of the javac design. Lots of classes with lots of visitors everywhere, and various ways to query "are you a T". I would like very much, one day, to make the Type/Symbol/Tree hierarchies sealed, and get rid of all the various kinds/tags, etc. and maybe even see if we can get rid of visitors and just use plain code with pattern matching. Maurizio On 26/11/2025 13:01, Liam Miller-Cushon wrote: > Hi, > > I wanted to discuss how javac handles end positions, and get input on > the possibility of having the compiler unconditionally store end > positions in a field on JCTree instead of in a separate map. > > Currently end position information is not stored by default, but is > enabled in certain modes: if?-Xjcov is set, or if the compilation > includes diagnostic listeners, task listeners, or annotation > processors (since they may want end positions). > > The hash table used to store the end positions?was optimized in JDK 9 > in?JDK-8033287, and there was some related discussion on compiler-dev@ > about the motivation?for making end positions?optional at that time. > > As I understand it, the goal is to?save memory in the case where end > positions aren't needed. That savings comes with?a trade-off when end > positions are needed, though, since the map is less efficient than > storing the position directly in JCTree. > > Today, many invocations of javac will need end position information > (annotation processing is common, when javac is used programatically > in IDEs end positions will be enabled). For the invocations that do > not need end positions, typical developer machines are less memory > constrained than they were when the optimization for end positions was > first introduced. > > Looking at the compilation of java.base, it contains about 3000 files > and creates about 3 million AST nodes, so adding an int field to > JCTree to store end positions would take about 12MB. > > What do you think? Would it make sense to consider adding a field to > JCTree to store end positions, instead of using EndPosTable? > > I have a draft PR of the approach here: > https://github.com/openjdk/jdk/pull/28506 > > Having end position information always available might enable some > potential improvements to javac. For example, some compilers indicate > a span of source text for some diagnostics, for example the 'range > highlighting' described in these clang docs: > https://clang.llvm.org/diagnostics.html