From prappo at openjdk.org Wed Oct 1 13:26:52 2025 From: prappo at openjdk.org (Pavel Rappo) Date: Wed, 1 Oct 2025 13:26:52 GMT Subject: RFR: 8367704: Fix minor documentation issues in java.time.** [v8] In-Reply-To: References: Message-ID: > Please review this documentation-only change, which I believe does **NOT** require CSR. > > The change touches java.time.** classes that I happen to have been using a lot recently. While the diff is pretty self-describing, here's the summary of what I did: > > * used a comma separator for some big integer values, to improve readability; > * fixed a few typos and grammar. > > While I'm open to discuss the change, I also have some questions. Note: I'm not attempting to address those questions in this PR. > > * What's the significance of the second argument in Duration.between(Temporal, Temporal) being exclusive? For example, would the result of the following call be different if the second argument was inclusive? > > Duration.between(Instant.ofEpochSecond(1), Instant.ofEpochSecond(2)) > > Are there any cases here where that distinction matters? > > * In many cases, the following phrase is used throughout documentation: > > > positive or negative > > While the intent is clearly to stress the directed nature of values, shouldn't we -- for completeness -- also mention zero where applicable? > > * What's the significance of title-case for Java Time-Scale? FWIW, the documentation also uses "Java time-scale". Pavel Rappo 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 11 additional commits since the last revision: - Merge remote-tracking branch 'jdk/master' into java.time - Revert this tiny change "Should" still feels out of place, but it's the same text copied across multiple packages. So it's better to leave it as is. - Remove CSR-triggering changes - An empty commit to kick GHA - Update src/java.base/share/classes/java/time/temporal/ChronoField.java Co-authored-by: Justin Lu - Update copyright years Note: any commit hashes below might be outdated due to subsequent history rewriting (e.g. git rebase). + update src/java.base/share/classes/java/time/package-info.java due to e58c5a4c023 + update src/java.base/share/classes/java/time/temporal/ChronoField.java due to 4d8aadf8754 - A few more typos - Extra typos and decimal separator - Use comma as a decimal separator - Fix Duration.abs - ... and 1 more: https://git.openjdk.org/jdk/compare/6e4fc3db...47c0d45f ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27296/files - new: https://git.openjdk.org/jdk/pull/27296/files/7c4cc716..47c0d45f Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27296&range=07 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27296&range=06-07 Stats: 153876 lines in 1576 files changed: 128305 ins; 14999 del; 10572 mod Patch: https://git.openjdk.org/jdk/pull/27296.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27296/head:pull/27296 PR: https://git.openjdk.org/jdk/pull/27296 From prappo at openjdk.org Wed Oct 1 13:26:54 2025 From: prappo at openjdk.org (Pavel Rappo) Date: Wed, 1 Oct 2025 13:26:54 GMT Subject: RFR: 8367704: Fix minor documentation issues in java.time.** [v7] In-Reply-To: References: Message-ID: On Wed, 17 Sep 2025 16:28:06 GMT, Roger Riggs wrote: >> Pavel Rappo has updated the pull request incrementally with one additional commit since the last revision: >> >> Remove CSR-triggering changes > > Keeping the change to typos removes the necessity of the the CSR. @RogerRiggs, @naotoj, please re-review this PR. If you are okay with that latest trivial change, I will integrate the PR today. Thanks. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27296#issuecomment-3356302262 From rriggs at openjdk.org Wed Oct 1 13:30:50 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Wed, 1 Oct 2025 13:30:50 GMT Subject: RFR: 8368825: Use switch expression for DateTimeFormatterBuilder pattern character lookup [v4] In-Reply-To: References: Message-ID: On Tue, 30 Sep 2025 23:21:32 GMT, Shaojin Wen wrote: >> The DateTimeFormatterBuilder::FIELD_MAP previously used a Map for mapping pattern characters to TemporalField >> instances. This PR refactors that implementation to use a switch expression instead, which eliminates the need to hold a Map in >> memory. >> >> The switch expression approach offers these advantages: >> - No memory overhead for maintaining a HashMap structure >> - More direct character-to-field mapping without hash computation >> - Better code readability and maintainability >> >> This change maintains the same functionality while improving the memory efficiency of pattern character lookup in >> DateTimeFormatterBuilder by eliminating the static Map that was previously used for character-to-field mapping. >> >> * before >> image > > Shaojin Wen has updated the pull request incrementally with one additional commit since the last revision: > > revert comment @liach Marked as reviewed by rriggs (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/26634#pullrequestreview-3289145865 From rriggs at openjdk.org Wed Oct 1 13:50:29 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Wed, 1 Oct 2025 13:50:29 GMT Subject: RFR: 8367704: Fix minor documentation issues in java.time.** [v8] In-Reply-To: References: Message-ID: On Wed, 1 Oct 2025 13:26:52 GMT, Pavel Rappo wrote: >> Please review this documentation-only change, which I believe does **NOT** require CSR. >> >> The change touches java.time.** classes that I happen to have been using a lot recently. While the diff is pretty self-describing, here's the summary of what I did: >> >> * used a comma separator for some big integer values, to improve readability; >> * fixed a few typos and grammar. >> >> While I'm open to discuss the change, I also have some questions. Note: I'm not attempting to address those questions in this PR. >> >> * What's the significance of the second argument in Duration.between(Temporal, Temporal) being exclusive? For example, would the result of the following call be different if the second argument was inclusive? >> >> Duration.between(Instant.ofEpochSecond(1), Instant.ofEpochSecond(2)) >> >> Are there any cases here where that distinction matters? >> >> * In many cases, the following phrase is used throughout documentation: >> >> > positive or negative >> >> While the intent is clearly to stress the directed nature of values, shouldn't we -- for completeness -- also mention zero where applicable? >> >> * What's the significance of title-case for Java Time-Scale? FWIW, the documentation also uses "Java time-scale". > > Pavel Rappo 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 11 additional commits since the last revision: > > - Merge remote-tracking branch 'jdk/master' into java.time > - Revert this tiny change > > "Should" still feels out of place, but it's the same text > copied across multiple packages. So it's better to leave > it as is. > - Remove CSR-triggering changes > - An empty commit to kick GHA > - Update src/java.base/share/classes/java/time/temporal/ChronoField.java > > Co-authored-by: Justin Lu > - Update copyright years > > Note: any commit hashes below might be outdated due to subsequent > history rewriting (e.g. git rebase). > > + update src/java.base/share/classes/java/time/package-info.java due to e58c5a4c023 > + update src/java.base/share/classes/java/time/temporal/ChronoField.java due to 4d8aadf8754 > - A few more typos > - Extra typos and decimal separator > - Use comma as a decimal separator > - Fix Duration.abs > - ... and 1 more: https://git.openjdk.org/jdk/compare/1bf00fe7...47c0d45f Thanks for the updates. ------------- Marked as reviewed by rriggs (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27296#pullrequestreview-3289252250 From naoto at openjdk.org Wed Oct 1 15:57:00 2025 From: naoto at openjdk.org (Naoto Sato) Date: Wed, 1 Oct 2025 15:57:00 GMT Subject: RFR: 8368825: Use switch expression for DateTimeFormatterBuilder pattern character lookup [v4] In-Reply-To: References: Message-ID: <03DIrJA3CcONrHoKW1eji6ri8XydMjwxuaDb8Eu8ix4=.a95d8913-2c41-4d02-b53e-63d761fd5966@github.com> On Tue, 30 Sep 2025 23:21:32 GMT, Shaojin Wen wrote: >> The DateTimeFormatterBuilder::FIELD_MAP previously used a Map for mapping pattern characters to TemporalField >> instances. This PR refactors that implementation to use a switch expression instead, which eliminates the need to hold a Map in >> memory. >> >> The switch expression approach offers these advantages: >> - No memory overhead for maintaining a HashMap structure >> - More direct character-to-field mapping without hash computation >> - Better code readability and maintainability >> >> This change maintains the same functionality while improving the memory efficiency of pattern character lookup in >> DateTimeFormatterBuilder by eliminating the static Map that was previously used for character-to-field mapping. >> >> * before >> image > > Shaojin Wen has updated the pull request incrementally with one additional commit since the last revision: > > revert comment @liach Marked as reviewed by naoto (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/26634#pullrequestreview-3289923824 From naoto at openjdk.org Wed Oct 1 16:02:32 2025 From: naoto at openjdk.org (Naoto Sato) Date: Wed, 1 Oct 2025 16:02:32 GMT Subject: RFR: 8367704: Fix minor documentation issues in java.time.** [v8] In-Reply-To: References: Message-ID: On Wed, 1 Oct 2025 13:26:52 GMT, Pavel Rappo wrote: >> Please review this documentation-only change, which I believe does **NOT** require CSR. >> >> The change touches java.time.** classes that I happen to have been using a lot recently. While the diff is pretty self-describing, here's the summary of what I did: >> >> * used a comma separator for some big integer values, to improve readability; >> * fixed a few typos and grammar. >> >> While I'm open to discuss the change, I also have some questions. Note: I'm not attempting to address those questions in this PR. >> >> * What's the significance of the second argument in Duration.between(Temporal, Temporal) being exclusive? For example, would the result of the following call be different if the second argument was inclusive? >> >> Duration.between(Instant.ofEpochSecond(1), Instant.ofEpochSecond(2)) >> >> Are there any cases here where that distinction matters? >> >> * In many cases, the following phrase is used throughout documentation: >> >> > positive or negative >> >> While the intent is clearly to stress the directed nature of values, shouldn't we -- for completeness -- also mention zero where applicable? >> >> * What's the significance of title-case for Java Time-Scale? FWIW, the documentation also uses "Java time-scale". > > Pavel Rappo 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 11 additional commits since the last revision: > > - Merge remote-tracking branch 'jdk/master' into java.time > - Revert this tiny change > > "Should" still feels out of place, but it's the same text > copied across multiple packages. So it's better to leave > it as is. > - Remove CSR-triggering changes > - An empty commit to kick GHA > - Update src/java.base/share/classes/java/time/temporal/ChronoField.java > > Co-authored-by: Justin Lu > - Update copyright years > > Note: any commit hashes below might be outdated due to subsequent > history rewriting (e.g. git rebase). > > + update src/java.base/share/classes/java/time/package-info.java due to e58c5a4c023 > + update src/java.base/share/classes/java/time/temporal/ChronoField.java due to 4d8aadf8754 > - A few more typos > - Extra typos and decimal separator > - Use comma as a decimal separator > - Fix Duration.abs > - ... and 1 more: https://git.openjdk.org/jdk/compare/8c55a4b1...47c0d45f Marked as reviewed by naoto (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27296#pullrequestreview-3289939501 From prappo at openjdk.org Wed Oct 1 16:05:07 2025 From: prappo at openjdk.org (Pavel Rappo) Date: Wed, 1 Oct 2025 16:05:07 GMT Subject: RFR: 8367704: Fix minor documentation issues in java.time.** [v8] In-Reply-To: References: Message-ID: On Wed, 1 Oct 2025 13:26:52 GMT, Pavel Rappo wrote: >> Please review this documentation-only change, which I believe does **NOT** require CSR. >> >> The change touches java.time.** classes that I happen to have been using a lot recently. While the diff is pretty self-describing, here's the summary of what I did: >> >> * used a comma separator for some big integer values, to improve readability; >> * fixed a few typos and grammar. >> >> While I'm open to discuss the change, I also have some questions. Note: I'm not attempting to address those questions in this PR. >> >> * What's the significance of the second argument in Duration.between(Temporal, Temporal) being exclusive? For example, would the result of the following call be different if the second argument was inclusive? >> >> Duration.between(Instant.ofEpochSecond(1), Instant.ofEpochSecond(2)) >> >> Are there any cases here where that distinction matters? >> >> * In many cases, the following phrase is used throughout documentation: >> >> > positive or negative >> >> While the intent is clearly to stress the directed nature of values, shouldn't we -- for completeness -- also mention zero where applicable? >> >> * What's the significance of title-case for Java Time-Scale? FWIW, the documentation also uses "Java time-scale". > > Pavel Rappo 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 11 additional commits since the last revision: > > - Merge remote-tracking branch 'jdk/master' into java.time > - Revert this tiny change > > "Should" still feels out of place, but it's the same text > copied across multiple packages. So it's better to leave > it as is. > - Remove CSR-triggering changes > - An empty commit to kick GHA > - Update src/java.base/share/classes/java/time/temporal/ChronoField.java > > Co-authored-by: Justin Lu > - Update copyright years > > Note: any commit hashes below might be outdated due to subsequent > history rewriting (e.g. git rebase). > > + update src/java.base/share/classes/java/time/package-info.java due to e58c5a4c023 > + update src/java.base/share/classes/java/time/temporal/ChronoField.java due to 4d8aadf8754 > - A few more typos > - Extra typos and decimal separator > - Use comma as a decimal separator > - Fix Duration.abs > - ... and 1 more: https://git.openjdk.org/jdk/compare/6e72c19e...47c0d45f Okay, thanks. Since java.time is not covered by tier1, which is what GHA runs, I did this additionally on my machine: % make test TEST="test/jdk/java/time/" ... ============================== Test summary ============================== TEST TOTAL PASS FAIL ERROR SKIP jtreg:test/jdk/java/time 187 187 0 0 0 ============================== TEST SUCCESS ------------- PR Comment: https://git.openjdk.org/jdk/pull/27296#issuecomment-3357097001 From prappo at openjdk.org Wed Oct 1 16:08:41 2025 From: prappo at openjdk.org (Pavel Rappo) Date: Wed, 1 Oct 2025 16:08:41 GMT Subject: Integrated: 8367704: Fix minor documentation issues in java.time.** In-Reply-To: References: Message-ID: On Mon, 15 Sep 2025 15:17:29 GMT, Pavel Rappo wrote: > Please review this documentation-only change, which I believe does **NOT** require CSR. > > The change touches java.time.** classes that I happen to have been using a lot recently. While the diff is pretty self-describing, here's the summary of what I did: > > * used a comma separator for some big integer values, to improve readability; > * fixed a few typos and grammar. > > While I'm open to discuss the change, I also have some questions. Note: I'm not attempting to address those questions in this PR. > > * What's the significance of the second argument in Duration.between(Temporal, Temporal) being exclusive? For example, would the result of the following call be different if the second argument was inclusive? > > Duration.between(Instant.ofEpochSecond(1), Instant.ofEpochSecond(2)) > > Are there any cases here where that distinction matters? > > * In many cases, the following phrase is used throughout documentation: > > > positive or negative > > While the intent is clearly to stress the directed nature of values, shouldn't we -- for completeness -- also mention zero where applicable? > > * What's the significance of title-case for Java Time-Scale? FWIW, the documentation also uses "Java time-scale". This pull request has now been integrated. Changeset: e44ef0c3 Author: Pavel Rappo URL: https://git.openjdk.org/jdk/commit/e44ef0c32b3c2fcd0a6293838d9185b6d0719219 Stats: 36 lines in 8 files changed: 0 ins; 0 del; 36 mod 8367704: Fix minor documentation issues in java.time.** Reviewed-by: naoto, rriggs ------------- PR: https://git.openjdk.org/jdk/pull/27296 From jlu at openjdk.org Wed Oct 1 18:02:49 2025 From: jlu at openjdk.org (Justin Lu) Date: Wed, 1 Oct 2025 18:02:49 GMT Subject: Integrated: 6177299: [Fmt-Nu] NumberFormat.getPercentInstance() does not work correctly In-Reply-To: References: Message-ID: <7QqLWmbtCXGPM5tYbAacAJekA1DCZ7Mx7L8zJXp6alc=.383938b5-9fe8-479e-a0da-67c95d2c7d02@github.com> On Mon, 29 Sep 2025 21:38:28 GMT, Justin Lu wrote: > Please review this PR which corrects an edge case bug for `DecimalFormat` parsing when a multiplier is applied. > > This issue applies to any parsed Strings whose resultant double value is rounded to _9.223372036854776E18_ after the multiplier is applied. The returned value is incorrectly given as `Long.MAX_VALUE` when it should be returned as the double _9.223372036854776E18_. > > For example, the String _"922,337,203,685,477,600,000%"_ is first parsed as _9.223372036854776E20_, after which the multiplier is then applied to give _9.223372036854776E18_. The original code evaluates `9.223372036854776E18 == (double)(long)9.223372036854776E18` as true, leading to the long representation returned. > > The double value should first be checked if it is within the long min/max range before being checked if it can be represented as a long. Note that the check should be inclusive, as during the comparison, `Long.MAX_VALUE` is promoted to _9.223372036854776E18_. Thus _9.223372036854775E18_ correctly compares as false, and all doubles above compare as true. This pull request has now been integrated. Changeset: 6b72b778 Author: Justin Lu URL: https://git.openjdk.org/jdk/commit/6b72b778039afce0e25986114d15dd29a6786529 Stats: 44 lines in 2 files changed: 40 ins; 0 del; 4 mod 6177299: [Fmt-Nu] NumberFormat.getPercentInstance() does not work correctly Reviewed-by: naoto ------------- PR: https://git.openjdk.org/jdk/pull/27563 From naoto at openjdk.org Wed Oct 1 20:01:58 2025 From: naoto at openjdk.org (Naoto Sato) Date: Wed, 1 Oct 2025 20:01:58 GMT Subject: RFR: 8368845: x-IBM930 uses incorrect character for Hex 42 60 Message-ID: <0Ep8UN3_bJ-nR9RCNIUaRA7flGGV3khNSjstui2ijRk=.d3eb41c7-1bae-4916-9c80-876d5912724f@github.com> Fixing a charset en/decoder for x-IBM930. There was a "temporary" mapping for the said code point for the backward compatibility (as of JDK7). Since the issue requests the "correct" mapping, I believe we can replace the temporary one with the correct mapping. ------------- Commit messages: - initial commit Changes: https://git.openjdk.org/jdk/pull/27594/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27594&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8368845 Stats: 15 lines in 3 files changed: 0 ins; 13 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/27594.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27594/head:pull/27594 PR: https://git.openjdk.org/jdk/pull/27594 From rriggs at openjdk.org Wed Oct 1 20:19:34 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Wed, 1 Oct 2025 20:19:34 GMT Subject: RFR: 8368172: Make java.time.format.DateTimePrintContext immutable [v4] In-Reply-To: References: <5xcmzM6BhoL-zhBZc_TrRSDCKBrOMqq8bRcmihc1zpU=.732bd228-f9ff-43f0-9771-56645dab6cd2@github.com> Message-ID: On Fri, 26 Sep 2025 04:04:40 GMT, Shaojin Wen wrote: >> I propose to make j.t.f.DateTimePrintContext immutable. >> >> Currently, DateTimePrintContext has only one mutable field, optional. This can be replaced by adding an optional parameter to the DateTimeFormatter.formatTo method. >> >> Immutable DateTimePrintContext can be optimized by escape analysis, such as immutable object optimization. > > Shaojin Wen has updated the pull request incrementally with one additional commit since the last revision: > > add DateTimePrinterParser#withOptional, from @RogerRiggs The necessity to replace the nested PrinterParsers in CompositPrinterParser.withOptional is an ugly feature of the design. At some point, someone will complain about that waste of memory and overhead. Only the composite printer has the static optional attribute. The rest are due to the nesting and it is a reasonable design choice to pass explicitly to each formatter as in cac20038d26a6e836cf427deee8a0942a23acc4d. It would be good to keep the design optional in parsing to be aligned with the PrinterParser design to avoid the designs drifting apart. And the documentation should more completely describe how the static and nested optionality cases are complementary. ------------- PR Comment: https://git.openjdk.org/jdk/pull/26913#issuecomment-3357981670 From jlu at openjdk.org Wed Oct 1 20:43:05 2025 From: jlu at openjdk.org (Justin Lu) Date: Wed, 1 Oct 2025 20:43:05 GMT Subject: RFR: 8368845: x-IBM930 uses incorrect character for Hex 42 60 In-Reply-To: <0Ep8UN3_bJ-nR9RCNIUaRA7flGGV3khNSjstui2ijRk=.d3eb41c7-1bae-4916-9c80-876d5912724f@github.com> References: <0Ep8UN3_bJ-nR9RCNIUaRA7flGGV3khNSjstui2ijRk=.d3eb41c7-1bae-4916-9c80-876d5912724f@github.com> Message-ID: On Wed, 1 Oct 2025 19:50:49 GMT, Naoto Sato wrote: > Fixing a charset en/decoder for x-IBM930. There was a "temporary" mapping for the said code point for the backward compatibility (as of JDK7). Since the issue requests the "correct" mapping, I believe we can replace the temporary one with the correct mapping. Should we add a test to confirm the swap to the new behavior? ------------- PR Comment: https://git.openjdk.org/jdk/pull/27594#issuecomment-3358062301 From naoto at openjdk.org Wed Oct 1 21:06:19 2025 From: naoto at openjdk.org (Naoto Sato) Date: Wed, 1 Oct 2025 21:06:19 GMT Subject: RFR: 8368845: x-IBM930 uses incorrect character for Hex 42 60 [v2] In-Reply-To: <0Ep8UN3_bJ-nR9RCNIUaRA7flGGV3khNSjstui2ijRk=.d3eb41c7-1bae-4916-9c80-876d5912724f@github.com> References: <0Ep8UN3_bJ-nR9RCNIUaRA7flGGV3khNSjstui2ijRk=.d3eb41c7-1bae-4916-9c80-876d5912724f@github.com> Message-ID: > Fixing a charset en/decoder for x-IBM930. There was a "temporary" mapping for the said code point for the backward compatibility (as of JDK7). Since the issue requests the "correct" mapping, I believe we can replace the temporary one with the correct mapping. Naoto Sato has updated the pull request incrementally with one additional commit since the last revision: added bugid to the tests ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27594/files - new: https://git.openjdk.org/jdk/pull/27594/files/bd338444..30ba5ce5 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27594&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27594&range=00-01 Stats: 7 lines in 3 files changed: 1 ins; 0 del; 6 mod Patch: https://git.openjdk.org/jdk/pull/27594.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27594/head:pull/27594 PR: https://git.openjdk.org/jdk/pull/27594 From naoto at openjdk.org Wed Oct 1 21:06:21 2025 From: naoto at openjdk.org (Naoto Sato) Date: Wed, 1 Oct 2025 21:06:21 GMT Subject: RFR: 8368845: x-IBM930 uses incorrect character for Hex 42 60 In-Reply-To: References: <0Ep8UN3_bJ-nR9RCNIUaRA7flGGV3khNSjstui2ijRk=.d3eb41c7-1bae-4916-9c80-876d5912724f@github.com> Message-ID: On Wed, 1 Oct 2025 20:40:39 GMT, Justin Lu wrote: > Should we add a test to confirm the swap to the new behavior? I had added the test data for the new mapping (Cp930.b2c) which is used for several test cases. Added the bug id to the relevant tests which should make it clearer. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27594#issuecomment-3358124998 From jlu at openjdk.org Wed Oct 1 21:17:37 2025 From: jlu at openjdk.org (Justin Lu) Date: Wed, 1 Oct 2025 21:17:37 GMT Subject: RFR: 8368981: Case Fold Locale Legacy Tags On Demand Message-ID: Please review this PR which case folds grandfathered BCP47 tags on demand. (Instead of keeping the case compliant versions stored.) This facilitates the cleanup of the `LEGACY` map (which contains a String to String Array mapping). The 2D String array, creation and populating of the `LEGACY` map, as well as lower case folding of the legacy tags can now be removed from the static block of _sun.util.locale.LanguageTag_. Legacy tags are a small subset compared to the entire set of valid BCP47 tags. Reducing the cost for supporting them would be ideal. Instead, legacy tags can now be checked against and folded on demand via a switch statement. The commented grandfathered syntax is removed because the values themselves already exist as code, and the exact case can be found in the provided RFC link. ------------- Commit messages: - Bolstering case folding test cases for legacy tags - inline 'potentialLegacy' and 'modern' - init Changes: https://git.openjdk.org/jdk/pull/27596/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27596&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8368981 Stats: 208 lines in 2 files changed: 100 ins; 90 del; 18 mod Patch: https://git.openjdk.org/jdk/pull/27596.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27596/head:pull/27596 PR: https://git.openjdk.org/jdk/pull/27596 From naoto at openjdk.org Wed Oct 1 22:05:47 2025 From: naoto at openjdk.org (Naoto Sato) Date: Wed, 1 Oct 2025 22:05:47 GMT Subject: RFR: 8368981: Case Fold Locale Legacy Tags On Demand In-Reply-To: References: Message-ID: On Wed, 1 Oct 2025 21:11:53 GMT, Justin Lu wrote: > Please review this PR which case folds grandfathered BCP47 tags on demand. (Instead of keeping the case compliant versions stored.) > > This facilitates the cleanup of the `LEGACY` map (which contains a String to String Array mapping). The 2D String array, creation and populating of the `LEGACY` map, as well as lower case folding of the legacy tags can now be removed from the static block of _sun.util.locale.LanguageTag_. > > Legacy tags are a small subset compared to the entire set of valid BCP47 tags. Reducing the cost for supporting them would be ideal. Instead, legacy tags can now be checked against and folded on demand via a switch statement. > > The commented grandfathered syntax is removed because the values themselves already exist as code, and the exact case can be found in the provided RFC link. Looks good. Some minor comments follow src/java.base/share/classes/sun/util/locale/LanguageTag.java line 111: > 109: > 110: // Check if the tag is a legacy tag > 111: var modern = legacyToModern(LocaleUtils.toLowerString(languageTag)); I'd use "preferred" instead of "modern", as it is used in the RFC. test/jdk/java/util/Locale/CaseFoldLanguageTagTest.java line 112: > 110: "zh-guoyu", > 111: "i-pwn", > 112: "i-mingo" Is this intentionally randomized? Otherwise I would like it to be sorted. ------------- PR Review: https://git.openjdk.org/jdk/pull/27596#pullrequestreview-3291289066 PR Review Comment: https://git.openjdk.org/jdk/pull/27596#discussion_r2396010744 PR Review Comment: https://git.openjdk.org/jdk/pull/27596#discussion_r2396013611 From jlu at openjdk.org Wed Oct 1 22:51:30 2025 From: jlu at openjdk.org (Justin Lu) Date: Wed, 1 Oct 2025 22:51:30 GMT Subject: RFR: 8368981: Case Fold Locale Legacy Tags On Demand [v2] In-Reply-To: References: Message-ID: > Please review this PR which case folds grandfathered BCP47 tags on demand. (Instead of keeping the case compliant versions stored.) > > This facilitates the cleanup of the `LEGACY` map (which contains a String to String Array mapping). The 2D String array, creation and populating of the `LEGACY` map, as well as lower case folding of the legacy tags can now be removed from the static block of _sun.util.locale.LanguageTag_. > > Legacy tags are a small subset compared to the entire set of valid BCP47 tags. Reducing the cost for supporting them would be ideal. Instead, legacy tags can now be checked against and folded on demand via a switch statement. > > The commented grandfathered syntax is removed because the values themselves already exist as code, and the exact case can be found in the provided RFC link. Justin Lu has updated the pull request incrementally with one additional commit since the last revision: implemenet Naoto's review ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27596/files - new: https://git.openjdk.org/jdk/pull/27596/files/710d7737..3720e24a Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27596&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27596&range=00-01 Stats: 40 lines in 2 files changed: 15 ins; 15 del; 10 mod Patch: https://git.openjdk.org/jdk/pull/27596.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27596/head:pull/27596 PR: https://git.openjdk.org/jdk/pull/27596 From jlu at openjdk.org Wed Oct 1 22:51:30 2025 From: jlu at openjdk.org (Justin Lu) Date: Wed, 1 Oct 2025 22:51:30 GMT Subject: RFR: 8368981: Case Fold Locale Legacy Tags On Demand [v2] In-Reply-To: References: Message-ID: <0ERKiGbLdQe_k6CuJMiS877HpgA1gAQ1nyOwXEybFCo=.a6837f5f-c6ad-4f81-9196-0c5ea2cf858c@github.com> On Wed, 1 Oct 2025 22:02:11 GMT, Naoto Sato wrote: >> Justin Lu has updated the pull request incrementally with one additional commit since the last revision: >> >> implemenet Naoto's review > > test/jdk/java/util/Locale/CaseFoldLanguageTagTest.java line 112: > >> 110: "zh-guoyu", >> 111: "i-pwn", >> 112: "i-mingo" > > Is this intentionally randomized? Otherwise I would like it to be sorted. No reason, just the order of what `entrySet()` gave me. It is now sorted. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27596#discussion_r2396112656 From naoto at openjdk.org Wed Oct 1 23:06:49 2025 From: naoto at openjdk.org (Naoto Sato) Date: Wed, 1 Oct 2025 23:06:49 GMT Subject: RFR: 8368981: Case Fold Locale Legacy Tags On Demand [v2] In-Reply-To: References: Message-ID: On Wed, 1 Oct 2025 22:51:30 GMT, Justin Lu wrote: >> Please review this PR which case folds grandfathered BCP47 tags on demand. (Instead of keeping the case compliant versions stored.) >> >> This facilitates the cleanup of the `LEGACY` map (which contains a String to String Array mapping). The 2D String array, creation and populating of the `LEGACY` map, as well as lower case folding of the legacy tags can now be removed from the static block of _sun.util.locale.LanguageTag_. >> >> Legacy tags are a small subset compared to the entire set of valid BCP47 tags. Reducing the cost for supporting them would be ideal. Instead, legacy tags can now be checked against and folded on demand via a switch statement. >> >> The commented grandfathered syntax is removed because the values themselves already exist as code, and the exact case can be found in the provided RFC link. > > Justin Lu has updated the pull request incrementally with one additional commit since the last revision: > > implemenet Naoto's review LGTM. Thanks for removing the (almost) unnecessary static initialization ------------- Marked as reviewed by naoto (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27596#pullrequestreview-3291472147 From swen at openjdk.org Thu Oct 2 02:17:31 2025 From: swen at openjdk.org (Shaojin Wen) Date: Thu, 2 Oct 2025 02:17:31 GMT Subject: RFR: 8368172: Make java.time.format.DateTimePrintContext immutable [v5] In-Reply-To: <5xcmzM6BhoL-zhBZc_TrRSDCKBrOMqq8bRcmihc1zpU=.732bd228-f9ff-43f0-9771-56645dab6cd2@github.com> References: <5xcmzM6BhoL-zhBZc_TrRSDCKBrOMqq8bRcmihc1zpU=.732bd228-f9ff-43f0-9771-56645dab6cd2@github.com> Message-ID: > I propose to make j.t.f.DateTimePrintContext immutable. > > Currently, DateTimePrintContext has only one mutable field, optional. This can be replaced by adding an optional parameter to the DateTimeFormatter.formatTo method. > > Immutable DateTimePrintContext can be optimized by escape analysis, such as immutable object optimization. Shaojin Wen has updated the pull request incrementally with one additional commit since the last revision: Revert "add DateTimePrinterParser#withOptional, from @RogerRiggs" This reverts commit 558fa46fa30093ff07e05e30a44ca0a86472e72e. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/26913/files - new: https://git.openjdk.org/jdk/pull/26913/files/558fa46f..5a7e2316 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=26913&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=26913&range=03-04 Stats: 322 lines in 2 files changed: 2 ins; 242 del; 78 mod Patch: https://git.openjdk.org/jdk/pull/26913.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/26913/head:pull/26913 PR: https://git.openjdk.org/jdk/pull/26913 From swen at openjdk.org Thu Oct 2 03:08:32 2025 From: swen at openjdk.org (Shaojin Wen) Date: Thu, 2 Oct 2025 03:08:32 GMT Subject: RFR: 8368172: Make java.time.format.DateTimePrintContext immutable [v6] In-Reply-To: <5xcmzM6BhoL-zhBZc_TrRSDCKBrOMqq8bRcmihc1zpU=.732bd228-f9ff-43f0-9771-56645dab6cd2@github.com> References: <5xcmzM6BhoL-zhBZc_TrRSDCKBrOMqq8bRcmihc1zpU=.732bd228-f9ff-43f0-9771-56645dab6cd2@github.com> Message-ID: <-MQxYO6i5RCnBQ-1NTwm5GcwucQgqYXIRHlFvsxO17A=.a6846ed0-8cc5-4501-9b94-cafa62a4909e@github.com> > I propose to make j.t.f.DateTimePrintContext immutable. > > Currently, DateTimePrintContext has only one mutable field, optional. This can be replaced by adding an optional parameter to the DateTimeFormatter.formatTo method. > > Immutable DateTimePrintContext can be optimized by escape analysis, such as immutable object optimization. Shaojin Wen has updated the pull request incrementally with one additional commit since the last revision: Improve javadoc for optional parameter in DateTimePrinterParser#format method ------------- Changes: - all: https://git.openjdk.org/jdk/pull/26913/files - new: https://git.openjdk.org/jdk/pull/26913/files/5a7e2316..6b35ea29 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=26913&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=26913&range=04-05 Stats: 5 lines in 1 file changed: 4 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/26913.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/26913/head:pull/26913 PR: https://git.openjdk.org/jdk/pull/26913 From scolebourne at openjdk.org Thu Oct 2 06:57:51 2025 From: scolebourne at openjdk.org (Stephen Colebourne) Date: Thu, 2 Oct 2025 06:57:51 GMT Subject: RFR: 8368825: Use switch expression for DateTimeFormatterBuilder pattern character lookup [v4] In-Reply-To: References: Message-ID: On Tue, 30 Sep 2025 23:21:32 GMT, Shaojin Wen wrote: >> The DateTimeFormatterBuilder::FIELD_MAP previously used a Map for mapping pattern characters to TemporalField >> instances. This PR refactors that implementation to use a switch expression instead, which eliminates the need to hold a Map in >> memory. >> >> The switch expression approach offers these advantages: >> - No memory overhead for maintaining a HashMap structure >> - More direct character-to-field mapping without hash computation >> - Better code readability and maintainability >> >> This change maintains the same functionality while improving the memory efficiency of pattern character lookup in >> DateTimeFormatterBuilder by eliminating the static Map that was previously used for character-to-field mapping. >> >> * before >> image > > Shaojin Wen has updated the pull request incrementally with one additional commit since the last revision: > > revert comment @liach Marked as reviewed by scolebourne (Author). ------------- PR Review: https://git.openjdk.org/jdk/pull/26634#pullrequestreview-3292808879 From rriggs at openjdk.org Thu Oct 2 13:26:52 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Thu, 2 Oct 2025 13:26:52 GMT Subject: RFR: 8368172: Make java.time.format.DateTimePrintContext immutable [v6] In-Reply-To: <-MQxYO6i5RCnBQ-1NTwm5GcwucQgqYXIRHlFvsxO17A=.a6846ed0-8cc5-4501-9b94-cafa62a4909e@github.com> References: <5xcmzM6BhoL-zhBZc_TrRSDCKBrOMqq8bRcmihc1zpU=.732bd228-f9ff-43f0-9771-56645dab6cd2@github.com> <-MQxYO6i5RCnBQ-1NTwm5GcwucQgqYXIRHlFvsxO17A=.a6846ed0-8cc5-4501-9b94-cafa62a4909e@github.com> Message-ID: On Thu, 2 Oct 2025 03:08:32 GMT, Shaojin Wen wrote: >> I propose to make j.t.f.DateTimePrintContext immutable. >> >> Currently, DateTimePrintContext has only one mutable field, optional. This can be replaced by adding an optional parameter to the DateTimeFormatter.formatTo method. >> >> Immutable DateTimePrintContext can be optimized by escape analysis, such as immutable object optimization. > > Shaojin Wen has updated the pull request incrementally with one additional commit since the last revision: > > Improve javadoc for optional parameter in DateTimePrinterParser#format method And one more thought/question: The optionality of formatting is a parameter used in the traversal of the formatting and parsing and affect nested formatting calls. The DateTimePrintContext previously counts the depth of the nesting with >0 indicating optional. It is the component that determines (based on optional:true) whether an absent value throws. Was it considered to change DateTimePrinterContext.optional to `final boolean optional` and create a second instance with optional=true. Only the CompositePrinterParser changes the state to indicate that nested PrinterParsers are optional. CompositePrinterParser could substitute the optional DateTimePrintContext. That would be closer to the current design and if allow it to be immutable. ------------- PR Comment: https://git.openjdk.org/jdk/pull/26913#issuecomment-3361215508 From swen at openjdk.org Thu Oct 2 13:35:14 2025 From: swen at openjdk.org (Shaojin Wen) Date: Thu, 2 Oct 2025 13:35:14 GMT Subject: Integrated: 8368825: Use switch expression for DateTimeFormatterBuilder pattern character lookup In-Reply-To: References: Message-ID: On Tue, 5 Aug 2025 01:42:53 GMT, Shaojin Wen wrote: > The DateTimeFormatterBuilder::FIELD_MAP previously used a Map for mapping pattern characters to TemporalField > instances. This PR refactors that implementation to use a switch expression instead, which eliminates the need to hold a Map in > memory. > > The switch expression approach offers these advantages: > - No memory overhead for maintaining a HashMap structure > - More direct character-to-field mapping without hash computation > - Better code readability and maintainability > > This change maintains the same functionality while improving the memory efficiency of pattern character lookup in > DateTimeFormatterBuilder by eliminating the static Map that was previously used for character-to-field mapping. > > * before > image This pull request has now been integrated. Changeset: 2c7f7380 Author: Shaojin Wen URL: https://git.openjdk.org/jdk/commit/2c7f7380ea828e5ec928e1cb05b13806646ecb3d Stats: 49 lines in 1 file changed: 7 ins; 0 del; 42 mod 8368825: Use switch expression for DateTimeFormatterBuilder pattern character lookup Reviewed-by: rriggs, naoto, scolebourne ------------- PR: https://git.openjdk.org/jdk/pull/26634 From swen at openjdk.org Thu Oct 2 13:39:52 2025 From: swen at openjdk.org (Shaojin Wen) Date: Thu, 2 Oct 2025 13:39:52 GMT Subject: RFR: 8368172: Make java.time.format.DateTimePrintContext immutable [v6] In-Reply-To: References: <5xcmzM6BhoL-zhBZc_TrRSDCKBrOMqq8bRcmihc1zpU=.732bd228-f9ff-43f0-9771-56645dab6cd2@github.com> <-MQxYO6i5RCnBQ-1NTwm5GcwucQgqYXIRHlFvsxO17A=.a6846ed0-8cc5-4501-9b94-cafa62a4909e@github.com> Message-ID: <2vNtq03FnpQvKBx4QnRGZGyilEoIcgHRv_SoxPneE3U=.6e1c2c8f-8a89-482c-b2c6-8484ac6cd64b@github.com> On Thu, 2 Oct 2025 13:24:25 GMT, Roger Riggs wrote: > And one more thought/question: The optionality of formatting is a parameter used in the traversal of the formatting and parsing and affect nested formatting calls. The DateTimePrintContext previously counts the depth of the nesting with >0 indicating optional. It is the component that determines (based on optional:true) whether an absent value throws. Was it considered to change DateTimePrinterContext.optional to `final boolean optional` and create a second instance with optional=true. > > Only the CompositePrinterParser changes the state to indicate that nested PrinterParsers are optional. CompositePrinterParser could substitute the optional DateTimePrintContext. That would be closer to the current design and if allow it to be immutable. It seems strange that the formatting process creates a new DateTimePrintContext object. ------------- PR Comment: https://git.openjdk.org/jdk/pull/26913#issuecomment-3361262924 From rriggs at openjdk.org Thu Oct 2 14:24:23 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Thu, 2 Oct 2025 14:24:23 GMT Subject: RFR: 8368172: Make java.time.format.DateTimePrintContext immutable [v6] In-Reply-To: <-MQxYO6i5RCnBQ-1NTwm5GcwucQgqYXIRHlFvsxO17A=.a6846ed0-8cc5-4501-9b94-cafa62a4909e@github.com> References: <5xcmzM6BhoL-zhBZc_TrRSDCKBrOMqq8bRcmihc1zpU=.732bd228-f9ff-43f0-9771-56645dab6cd2@github.com> <-MQxYO6i5RCnBQ-1NTwm5GcwucQgqYXIRHlFvsxO17A=.a6846ed0-8cc5-4501-9b94-cafa62a4909e@github.com> Message-ID: On Thu, 2 Oct 2025 03:08:32 GMT, Shaojin Wen wrote: >> I propose to make j.t.f.DateTimePrintContext immutable. >> >> Currently, DateTimePrintContext has only one mutable field, optional. This can be replaced by adding an optional parameter to the DateTimeFormatter.formatTo method. >> >> Immutable DateTimePrintContext can be optimized by escape analysis, such as immutable object optimization. > > Shaojin Wen has updated the pull request incrementally with one additional commit since the last revision: > > Improve javadoc for optional parameter in DateTimePrinterParser#format method The DateTimePrintContext is exactly that, providing the context for the formatting. It holds the references to the Temporal that has the value and the appendable that is the destination. And in the committed implementation holds the current optional count/flag. If its is to be immutable, then you need to create a second one and pass it down to/through format(). It will be a small, short lived object. ------------- PR Comment: https://git.openjdk.org/jdk/pull/26913#issuecomment-3361450548 From swen at openjdk.org Thu Oct 2 14:36:17 2025 From: swen at openjdk.org (Shaojin Wen) Date: Thu, 2 Oct 2025 14:36:17 GMT Subject: RFR: 8368172: Make java.time.format.DateTimePrintContext immutable [v6] In-Reply-To: <-MQxYO6i5RCnBQ-1NTwm5GcwucQgqYXIRHlFvsxO17A=.a6846ed0-8cc5-4501-9b94-cafa62a4909e@github.com> References: <5xcmzM6BhoL-zhBZc_TrRSDCKBrOMqq8bRcmihc1zpU=.732bd228-f9ff-43f0-9771-56645dab6cd2@github.com> <-MQxYO6i5RCnBQ-1NTwm5GcwucQgqYXIRHlFvsxO17A=.a6846ed0-8cc5-4501-9b94-cafa62a4909e@github.com> Message-ID: On Thu, 2 Oct 2025 03:08:32 GMT, Shaojin Wen wrote: >> I propose to make j.t.f.DateTimePrintContext immutable. >> >> Currently, DateTimePrintContext has only one mutable field, optional. This can be replaced by adding an optional parameter to the DateTimeFormatter.formatTo method. >> >> Immutable DateTimePrintContext can be optimized by escape analysis, such as immutable object optimization. > > Shaojin Wen has updated the pull request incrementally with one additional commit since the last revision: > > Improve javadoc for optional parameter in DateTimePrinterParser#format method Creating a DateTimePrintContext during the formatting process also has a disadvantage: it is difficult to perform manual unrolling performance optimizations like the draft PR #26807 I submitted, and it also makes automatic unrolling by the C2 JIT more difficult. ------------- PR Comment: https://git.openjdk.org/jdk/pull/26913#issuecomment-3361498045 From rriggs at openjdk.org Thu Oct 2 15:05:59 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Thu, 2 Oct 2025 15:05:59 GMT Subject: RFR: 8368981: Case Fold Locale Legacy Tags On Demand [v2] In-Reply-To: References: Message-ID: On Wed, 1 Oct 2025 22:51:30 GMT, Justin Lu wrote: >> Please review this PR which case folds grandfathered BCP47 tags on demand. (Instead of keeping the case compliant versions stored.) >> >> This facilitates the cleanup of the `LEGACY` map (which contains a String to String Array mapping). The 2D String array, creation and populating of the `LEGACY` map, as well as lower case folding of the legacy tags can now be removed from the static block of _sun.util.locale.LanguageTag_. >> >> Legacy tags are a small subset compared to the entire set of valid BCP47 tags. Reducing the cost for supporting them would be ideal. Instead, legacy tags can now be checked against and folded on demand via a switch statement. >> >> The commented grandfathered syntax is removed because the values themselves already exist as code, and the exact case can be found in the provided RFC link. > > Justin Lu has updated the pull request incrementally with one additional commit since the last revision: > > implemenet Naoto's review src/java.base/share/classes/sun/util/locale/LanguageTag.java line 345: > 343: } > 344: } > 345: bldr.deleteCharAt(bldr.length() - 1); // Remove trailing '-' `bldr.setLength(bldr.length() - 1)` might be better? src/java.base/share/classes/sun/util/locale/LanguageTag.java line 516: > 514: if (tag.length() > 11 || tag.length() < 5) { > 515: return null; > 516: } I can see the < 5 having some saving if most of the tags are short. I doubt the > 11 saves anything and it creates a maintenance gotcha, if a tag is added that is longer. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27596#discussion_r2399143786 PR Review Comment: https://git.openjdk.org/jdk/pull/27596#discussion_r2399105662 From rriggs at openjdk.org Thu Oct 2 15:13:24 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Thu, 2 Oct 2025 15:13:24 GMT Subject: RFR: 8368172: Make java.time.format.DateTimePrintContext immutable [v6] In-Reply-To: <-MQxYO6i5RCnBQ-1NTwm5GcwucQgqYXIRHlFvsxO17A=.a6846ed0-8cc5-4501-9b94-cafa62a4909e@github.com> References: <5xcmzM6BhoL-zhBZc_TrRSDCKBrOMqq8bRcmihc1zpU=.732bd228-f9ff-43f0-9771-56645dab6cd2@github.com> <-MQxYO6i5RCnBQ-1NTwm5GcwucQgqYXIRHlFvsxO17A=.a6846ed0-8cc5-4501-9b94-cafa62a4909e@github.com> Message-ID: On Thu, 2 Oct 2025 03:08:32 GMT, Shaojin Wen wrote: >> I propose to make j.t.f.DateTimePrintContext immutable. >> >> Currently, DateTimePrintContext has only one mutable field, optional. This can be replaced by adding an optional parameter to the DateTimeFormatter.formatTo method. >> >> Immutable DateTimePrintContext can be optimized by escape analysis, such as immutable object optimization. > > Shaojin Wen has updated the pull request incrementally with one additional commit since the last revision: > > Improve javadoc for optional parameter in DateTimePrinterParser#format method I beginning to get concerned about the bloat in code cache created by this line of inquiry in the quest for microbenchmark performance. In cloud deployments, extra memory costs money. ------------- PR Comment: https://git.openjdk.org/jdk/pull/26913#issuecomment-3361663586 From naoto at openjdk.org Thu Oct 2 16:08:33 2025 From: naoto at openjdk.org (Naoto Sato) Date: Thu, 2 Oct 2025 16:08:33 GMT Subject: RFR: 8368981: Case Fold Locale Legacy Tags On Demand [v2] In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 14:52:20 GMT, Roger Riggs wrote: >> Justin Lu has updated the pull request incrementally with one additional commit since the last revision: >> >> implemenet Naoto's review > > src/java.base/share/classes/sun/util/locale/LanguageTag.java line 516: > >> 514: if (tag.length() > 11 || tag.length() < 5) { >> 515: return null; >> 516: } > > I can see the < 5 having some saving if most of the tags are short. > I doubt the > 11 saves anything and it creates a maintenance gotcha, if a tag is added that is longer. Per RFC, it is guaranteed that the list of the grandfathered (=legacy) tags will never change (https://datatracker.ietf.org/doc/html/rfc5646#section-2.1) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27596#discussion_r2399329170 From jlu at openjdk.org Thu Oct 2 16:58:41 2025 From: jlu at openjdk.org (Justin Lu) Date: Thu, 2 Oct 2025 16:58:41 GMT Subject: RFR: 8368981: Case Fold Locale Legacy Tags On Demand [v3] In-Reply-To: References: Message-ID: > Please review this PR which case folds grandfathered BCP47 tags on demand. (Instead of keeping the case compliant versions stored.) > > This facilitates the cleanup of the `LEGACY` map (which contains a String to String Array mapping). The 2D String array, creation and populating of the `LEGACY` map, as well as lower case folding of the legacy tags can now be removed from the static block of _sun.util.locale.LanguageTag_. > > Legacy tags are a small subset compared to the entire set of valid BCP47 tags. Reducing the cost for supporting them would be ideal. Instead, legacy tags can now be checked against and folded on demand via a switch statement. > > The commented grandfathered syntax is removed because the values themselves already exist as code, and the exact case can be found in the provided RFC link. Justin Lu has updated the pull request incrementally with one additional commit since the last revision: Implement Roger's review ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27596/files - new: https://git.openjdk.org/jdk/pull/27596/files/3720e24a..fb6b1dcc Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27596&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27596&range=01-02 Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/27596.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27596/head:pull/27596 PR: https://git.openjdk.org/jdk/pull/27596 From jlu at openjdk.org Thu Oct 2 16:58:43 2025 From: jlu at openjdk.org (Justin Lu) Date: Thu, 2 Oct 2025 16:58:43 GMT Subject: RFR: 8368981: Case Fold Locale Legacy Tags On Demand [v2] In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 16:06:07 GMT, Naoto Sato wrote: >> src/java.base/share/classes/sun/util/locale/LanguageTag.java line 516: >> >>> 514: if (tag.length() > 11 || tag.length() < 5) { >>> 515: return null; >>> 516: } >> >> I can see the < 5 having some saving if most of the tags are short. >> I doubt the > 11 saves anything and it creates a maintenance gotcha, if a tag is added that is longer. > > Per RFC, it is guaranteed that the list of the grandfathered (=legacy) tags will never change (https://datatracker.ietf.org/doc/html/rfc5646#section-2.1) Right, the reason we can have confidence in this shortcut check is that the list is specified to be stable. However, if there is likely no save on cost, then we can remove it. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27596#discussion_r2399453184 From rriggs at openjdk.org Thu Oct 2 19:49:47 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Thu, 2 Oct 2025 19:49:47 GMT Subject: RFR: 8368981: Case Fold Locale Legacy Tags On Demand [v3] In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 16:58:41 GMT, Justin Lu wrote: >> Please review this PR which case folds grandfathered BCP47 tags on demand. (Instead of keeping the case compliant versions stored.) >> >> This facilitates the cleanup of the `LEGACY` map (which contains a String to String Array mapping). The 2D String array, creation and populating of the `LEGACY` map, as well as lower case folding of the legacy tags can now be removed from the static block of _sun.util.locale.LanguageTag_. >> >> Legacy tags are a small subset compared to the entire set of valid BCP47 tags. Reducing the cost for supporting them would be ideal. Instead, legacy tags can now be checked against and folded on demand via a switch statement. >> >> The commented grandfathered syntax is removed because the values themselves already exist as code, and the exact case can be found in the provided RFC link. > > Justin Lu has updated the pull request incrementally with one additional commit since the last revision: > > Implement Roger's review LGTM ------------- Marked as reviewed by rriggs (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27596#pullrequestreview-3296165026 From swen at openjdk.org Fri Oct 3 09:10:46 2025 From: swen at openjdk.org (Shaojin Wen) Date: Fri, 3 Oct 2025 09:10:46 GMT Subject: RFR: 8368172: Make java.time.format.DateTimePrintContext immutable [v6] In-Reply-To: References: <5xcmzM6BhoL-zhBZc_TrRSDCKBrOMqq8bRcmihc1zpU=.732bd228-f9ff-43f0-9771-56645dab6cd2@github.com> <-MQxYO6i5RCnBQ-1NTwm5GcwucQgqYXIRHlFvsxO17A=.a6846ed0-8cc5-4501-9b94-cafa62a4909e@github.com> Message-ID: <_6CJOczFmBqEl2qBXgJEYoj3jc9RxAfhN-ieR92zRAw=.0fc6f1e5-5653-4ca4-8db5-58a860002e04@github.com> On Thu, 2 Oct 2025 15:11:05 GMT, Roger Riggs wrote: > I beginning to get concerned about the bloat in code cache created by this line of inquiry in the quest for microbenchmark performance. In cloud deployments, extra memory costs money. When the CodeCache memory space is insufficient, the JIT will discard the oldest compiled methods that are not currently in the execution stack; I think we don't need to worry about this. ------------- PR Comment: https://git.openjdk.org/jdk/pull/26913#issuecomment-3364888865 From prappo at openjdk.org Fri Oct 3 09:50:23 2025 From: prappo at openjdk.org (Pavel Rappo) Date: Fri, 3 Oct 2025 09:50:23 GMT Subject: RFR: 8366829: Add constants for the Duration MIN/MAX values [v3] In-Reply-To: References: Message-ID: > We have [recently discussed][] a possibility of adding the `Duration.MIN` and `Duration.MAX` constants. Can we now start implementation? If and when we are in agreement on this PR, I will file a CSR. > > I drafted a minimal specification and added some tests. I tried to phrase the spec for `Duration.MIN` in a way that makes it clear that `Duration.MIN` is the most negative value and not the least positive. > > [recently discussed]: https://mail.openjdk.org/pipermail/core-libs-dev/2025-September/151098.html Pavel Rappo has updated the pull request incrementally with one additional commit since the last revision: Respond to feedback Apply Stephen's suggestion on wording, although modified. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27534/files - new: https://git.openjdk.org/jdk/pull/27534/files/c5a3f228..abe01ff5 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27534&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27534&range=01-02 Stats: 18 lines in 1 file changed: 2 ins; 1 del; 15 mod Patch: https://git.openjdk.org/jdk/pull/27534.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27534/head:pull/27534 PR: https://git.openjdk.org/jdk/pull/27534 From jlu at openjdk.org Fri Oct 3 16:28:56 2025 From: jlu at openjdk.org (Justin Lu) Date: Fri, 3 Oct 2025 16:28:56 GMT Subject: RFR: 8368981: Case Fold Locale Legacy Tags On Demand [v3] In-Reply-To: References: Message-ID: <8vPRllD5nujUmTtZsCiC-AhlBVi1G_DCFuXVQT4biTo=.e39d8ddf-9ba5-4447-bfbb-c10c60c61b69@github.com> On Thu, 2 Oct 2025 16:58:41 GMT, Justin Lu wrote: >> Please review this PR which case folds grandfathered BCP47 tags on demand. (Instead of keeping the case compliant versions stored.) >> >> This facilitates the cleanup of the `LEGACY` map (which contains a String to String Array mapping). The 2D String array, creation and populating of the `LEGACY` map, as well as lower case folding of the legacy tags can now be removed from the static block of _sun.util.locale.LanguageTag_. >> >> Legacy tags are a small subset compared to the entire set of valid BCP47 tags. Reducing the cost for supporting them would be ideal. Instead, legacy tags can now be checked against and folded on demand via a switch statement. >> >> The commented grandfathered syntax is removed because the values themselves already exist as code, and the exact case can be found in the provided RFC link. > > Justin Lu has updated the pull request incrementally with one additional commit since the last revision: > > Implement Roger's review Thank you for the reviews! ------------- PR Comment: https://git.openjdk.org/jdk/pull/27596#issuecomment-3366355891 From jlu at openjdk.org Fri Oct 3 16:28:57 2025 From: jlu at openjdk.org (Justin Lu) Date: Fri, 3 Oct 2025 16:28:57 GMT Subject: Integrated: 8368981: Case Fold Locale Legacy Tags On Demand In-Reply-To: References: Message-ID: <2t4pwt6e4uOa9YOGmOoNeUmM0vmxrwSq5gatLH2lKMM=.eea1f7b4-504d-4891-95d9-05e8fca18eea@github.com> On Wed, 1 Oct 2025 21:11:53 GMT, Justin Lu wrote: > Please review this PR which case folds grandfathered BCP47 tags on demand. (Instead of keeping the case compliant versions stored.) > > This facilitates the cleanup of the `LEGACY` map (which contains a String to String Array mapping). The 2D String array, creation and populating of the `LEGACY` map, as well as lower case folding of the legacy tags can now be removed from the static block of _sun.util.locale.LanguageTag_. > > Legacy tags are a small subset compared to the entire set of valid BCP47 tags. Reducing the cost for supporting them would be ideal. Instead, legacy tags can now be checked against and folded on demand via a switch statement. > > The commented grandfathered syntax is removed because the values themselves already exist as code, and the exact case can be found in the provided RFC link. This pull request has now been integrated. Changeset: 23a65644 Author: Justin Lu URL: https://git.openjdk.org/jdk/commit/23a65644ae63b271ca99c55a2a60a192c4e4dfb8 Stats: 208 lines in 2 files changed: 100 ins; 90 del; 18 mod 8368981: Case Fold Locale Legacy Tags On Demand Reviewed-by: rriggs, naoto ------------- PR: https://git.openjdk.org/jdk/pull/27596 From naoto at openjdk.org Fri Oct 3 17:55:52 2025 From: naoto at openjdk.org (Naoto Sato) Date: Fri, 3 Oct 2025 17:55:52 GMT Subject: RFR: 8366829: Add java.time.Duration constants MIN and MAX [v3] In-Reply-To: References: Message-ID: On Fri, 3 Oct 2025 09:50:23 GMT, Pavel Rappo wrote: >> We have [recently discussed][] a possibility of adding the `Duration.MIN` and `Duration.MAX` constants. Can we now start implementation? If and when we are in agreement on this PR, I will file a CSR. >> >> I drafted a minimal specification and added some tests. I tried to phrase the spec for `Duration.MIN` in a way that makes it clear that `Duration.MIN` is the most negative value and not the least positive. >> >> [recently discussed]: https://mail.openjdk.org/pipermail/core-libs-dev/2025-September/151098.html > > Pavel Rappo has updated the pull request incrementally with one additional commit since the last revision: > > Respond to feedback > > Apply Stephen's suggestion on wording, although modified. Marked as reviewed by naoto (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27534#pullrequestreview-3300200546 From rriggs at openjdk.org Fri Oct 3 18:37:48 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Fri, 3 Oct 2025 18:37:48 GMT Subject: RFR: 8366829: Add java.time.Duration constants MIN and MAX [v3] In-Reply-To: References: Message-ID: On Fri, 3 Oct 2025 09:50:23 GMT, Pavel Rappo wrote: >> We have [recently discussed][] a possibility of adding the `Duration.MIN` and `Duration.MAX` constants. Can we now start implementation? If and when we are in agreement on this PR, I will file a CSR. >> >> I drafted a minimal specification and added some tests. I tried to phrase the spec for `Duration.MIN` in a way that makes it clear that `Duration.MIN` is the most negative value and not the least positive. >> >> [recently discussed]: https://mail.openjdk.org/pipermail/core-libs-dev/2025-September/151098.html > > Pavel Rappo has updated the pull request incrementally with one additional commit since the last revision: > > Respond to feedback > > Apply Stephen's suggestion on wording, although modified. Marked as reviewed by rriggs (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27534#pullrequestreview-3300388900 From sherman at openjdk.org Fri Oct 3 19:10:20 2025 From: sherman at openjdk.org (Xueming Shen) Date: Fri, 3 Oct 2025 19:10:20 GMT Subject: RFR: 8365675: Add String Unicode Case-Folding Support Message-ID: ### Summary Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions. Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as: **String.equalsIgnoreCase(String)** - Unicode-aware, locale-independent. - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point. - Limited: does not support 1:M mapping defined in Unicode case folding. **Character.toLowerCase(int) / Character.toUpperCase(int)** - Locale-independent, single code point only. - No support for 1:M mappings. **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)** - Based on Unicode SpecialCasing.txt, supports 1:M mappings. - Intended primarily for presentation/display, not structural case-insensitive matching. - Requires full string conversion before comparison, which is less efficient and not intended for structural matching. **1:M mapping example, U+00DF (?)** - String.toUpperCase(Locale.ROOT, "?") ? "SS" - Case folding produces "ss", matching Unicode caseless comparison rules. jshell> "\u00df".equalsIgnoreCase("ss") $22 ==> false jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss") $24 ==> true ### Motivation & Direction Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching. - Unicode-compliant **full** case folding. - Simpler, stable and more efficient case-less matching without workarounds. - Brings Java's string comparison handling in line with other programming languages/libraries. This PR proposes to introduce the following comparison methods in `String` class - boolean equalsFoldCase(String anotherString) - int compareToFoldCase(String anotherString) - Comparator UNICODE_CASEFOLD_ORDER These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required. *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string. However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then passed into APIs where case-folding semantics are not appropriate. ### The New API /** * Compares this {@code String} to another {@code String} for equality, * using Unicode case folding. Two strings are considered equal * by this method if their case-folded forms are identical. *

* Case folding is defined by the Unicode Standard in * CaseFolding.txt, * including 1:M mappings. For example, {@code "Ma?e".equalsFoldCase("MASSE")} * returns {@code true}, since the character {@code U+00DF} (sharp s) folds * to {@code "ss"}. *

* Case folding is locale-independent and language-neutral, unlike * locale-sensitive transformations such as {@link #toLowerCase()} or * {@link #toUpperCase()}. It is intended for caseless matching, * searching, and indexing. * * @apiNote * This method is the Unicode-compliant alternative to * {@link #equalsIgnoreCase(String)}. It implements full case folding as * defined by the Unicode Standard, which may differ from the simpler * per-character mapping performed by {@code equalsIgnoreCase}. * For example: *

{@snippet lang=java :
     * String a = "Ma?e";
     * String b = "MASSE";
     * boolean equalsFoldCase = a.equalsFoldCase(b);       // returns true
     * boolean equalsIgnoreCase = a.equalsIgnoreCase(b);   // returns false
     * }
* * @param anotherString * The {@code String} to compare this {@code String} against * * @return {@code true} if the given object is not {@code null} and represents * the same sequence of characters as this string under Unicode case * folding; {@code false} otherwise. * * @see #compareToFoldCase(String) * @see #equalsIgnoreCase(String) * @since 26 */ public boolean equalsFoldCase(String anotherString) /** * Compares two strings lexicographically using Unicode case folding. * This method returns an integer whose sign is that of calling {@code compareTo} * on the Unicode case folded version of the strings. Unicode Case folding * eliminates differences in case according to the Unicode Standard, using the * mappings defined in * CaseFolding.txt, * including 1:M mappings, such as {@code"?"} ? {@code }"ss"}. *

* Case folding is a locale-independent, language-neutral form of case mapping, * primarily intended for caseless matching. Unlike {@link #compareToIgnoreCase(String)}, * which applies a simpler locale-insensitive uppercase mapping. This method * follows the Unicode full case folding, providing stable and * consistent results across all environments. *

* Note that this method does not take locale into account, and may * produce results that differ from locale-sensitive ordering. Use * {@link java.text.Collator} for locale-sensitive comparison. * * @apiNote * This method is the Unicode-compliant alternative to * {@link #compareToIgnoreCase(String)}. It implements the full case folding * as defined by the Unicode Standard, which may differ from the simpler * per-character mapping performed by {@code compareToIgnoreCase}. * For example: *

{@snippet lang=java :
     * String a = "Ma?e";
     * String b = "MASSE";
     * int cmpFoldCase = a.compareToFoldCase(b);     // returns 0
     * int cmpIgnoreCase = a.compareToIgnoreCase(b); // returns > 0
     * }
* * @param str the {@code String} to be compared. * @return a negative integer, zero, or a positive integer as the specified * String is greater than, equal to, or less than this String, * ignoring case considerations by case folding. * @see #equalsFoldCase(String) * @see #compareToIgnoreCase(String) * @see java.text.Collator * @since 26 */ public int compareToFoldCase(String str) /** * A Comparator that orders {@code String} objects as by * {@link #compareToFoldCase(String) compareToFoldCase()}. * * @see #compareToFoldCase(String) * @since 26 */ public static final Comparator UNICODE_CASEFOLD_ORDER; ### Usage Examples Sharp s (U+00DF) case-folds to "ss" "stra?e".equalsIgnoreCase("strasse"); // false "stra?e".compareToIgnoreCase("strasse"); // != 0 "stra?e".equalsFoldCase("strasse"); // true ### Performance The JMH microbenchmark StringCompareToIgnoreCase has been updated to compare performance of compareToFoldCase with the existing compareToIgnoreCase(). Benchmark Mode Cnt Score Error Units StringCompareToIgnoreCase.asciiGreekLower avgt 15 20.195 ? 0.300 ns/op StringCompareToIgnoreCase.asciiGreekLowerCF avgt 15 11.051 ? 0.254 ns/op StringCompareToIgnoreCase.asciiGreekUpperLower avgt 15 6.035 ? 0.047 ns/op StringCompareToIgnoreCase.asciiGreekUpperLowerCF avgt 15 14.786 ? 0.382 ns/op StringCompareToIgnoreCase.asciiLower avgt 15 17.688 ? 1.396 ns/op StringCompareToIgnoreCase.asciiLowerCF avgt 15 44.552 ? 0.155 ns/op StringCompareToIgnoreCase.asciiUpperLower avgt 15 13.069 ? 0.487 ns/op StringCompareToIgnoreCase.asciiUpperLowerCF avgt 15 58.684 ? 0.274 ns/op StringCompareToIgnoreCase.greekLower avgt 15 20.642 ? 0.082 ns/op StringCompareToIgnoreCase.greekLowerCF avgt 15 7.255 ? 0.271 ns/op StringCompareToIgnoreCase.greekUpperLower avgt 15 5.737 ? 0.013 ns/op StringCompareToIgnoreCase.greekUpperLowerCF avgt 15 11.100 ? 1.147 ns/op StringCompareToIgnoreCase.lower avgt 15 20.192 ? 0.044 ns/op StringCompareToIgnoreCase.lowerrCF avgt 15 11.257 ? 0.259 ns/op StringCompareToIgnoreCase.supLower avgt 15 54.801 ? 0.415 ns/op StringCompareToIgnoreCase.supLowerCF avgt 15 15.207 ? 0.418 ns/op StringCompareToIgnoreCase.supUpperLower avgt 15 14.431 ? 0.188 ns/op StringCompareToIgnoreCase.supUpperLowerCF avgt 15 19.149 ? 0.985 ns/op StringCompareToIgnoreCase.upperLower avgt 15 5.650 ? 0.051 ns/op StringCompareToIgnoreCase.upperLowerCF avgt 15 14.338 ? 0.352 ns/op StringCompareToIgnoreCase.utf16SubLower avgt 15 14.774 ? 0.200 ns/op StringCompareToIgnoreCase.utf16SubLowerCF avgt 15 2.669 ? 0.041 ns/op StringCompareToIgnoreCase.utf16SupUpperLower avgt 15 16.250 ? 0.099 ns/op StringCompareToIgnoreCase.utf16SupUpperLowerCF avgt 15 11.524 ? 0.327 ns/op ### Refs [Unicode Standard 5.18.4 Caseless Matching](https://www.unicode.org/versions/latest/core-spec/chapter-5/#G21790) [Unicode? Standard Annex #44: 5.6 Case and Case Mapping](https://www.unicode.org/reports/tr44/#Casemapping) [Unicode Technical Standard #18: Unicode Regular Expressions RL1.5: Simple Loose Matches](https://www.unicode.org/reports/tr18/#Simple_Loose_Matches) [Unicode SpecialCasing.txt](https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt) [Unicode CaseFolding.txt](https://www.unicode.org/Public/UCD/latest/ucd/CaseFolding.txt) ### Other Languages **Python string.casefold()** The str.casefold() method in Python returns a casefolded version of a string. Casefolding is a more aggressive form of lowercasing, designed to remove all case distinctions in a string, particularly for the purpose of caseless string comparisons. **Perl?s fc()** Returns the casefolded version of EXPR. This is the internal function implementing the \F escape in double-quoted strings. Casefolding is the process of mapping strings to a form where case differences are erased; comparing two strings in their casefolded form is effectively a way of asking if two strings are equal, regardless of case. Perl only implements the full form of casefolding, but you can access the simple folds using "casefold()" in Unicode::UCD] ad "prop_invmap()" in Unicode::UCD]. **ICU4J UCharacter.foldCase (Java)** Purpose: Provides extensions to the standard Java Character class, including support for more Unicode properties and handling of supplementary characters (code points beyond U+FFFF). Method Signature (String based): public static String foldCase(String str, int options) Method Signature (CharSequence & Appendable based): public static A foldCase(CharSequence src, A dest, int options, Edits edits) Key Features: Case Folding: Converts a string to its case-folded equivalent. Locale Independent: Case folding in UCharacter.foldCase is generally not dependent on locale settings. Context Insensitive: The mapping of a character is not affected by surrounding characters. Turkic Option: An option exists to include or exclude special mappings for Turkish/Azerbaijani text. Result Length: The resulting string can be longer or shorter than the original. Edits Recording: Allows for recording of edits for index mapping, styled text, and getting only changes. **u_strFoldCase (C/C++)** A lower-level C API function for case folding a string. Case Folding Options: Similar options as UCharacter.foldCase for controlling case folding behavior. Availability: Found in the ustring.h and unistr.h headers in the ICU4C library. ------------- Commit messages: - 8365675: Add String Unicode Case-Folding Support Changes: https://git.openjdk.org/jdk/pull/26892/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=26892&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8365675 Stats: 1279 lines in 12 files changed: 1116 ins; 137 del; 26 mod Patch: https://git.openjdk.org/jdk/pull/26892.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/26892/head:pull/26892 PR: https://git.openjdk.org/jdk/pull/26892 From sherman at openjdk.org Fri Oct 3 19:41:20 2025 From: sherman at openjdk.org (Xueming Shen) Date: Fri, 3 Oct 2025 19:41:20 GMT Subject: RFR: 8365675: Add String Unicode Case-Folding Support [v2] In-Reply-To: References: Message-ID: > ### Summary > > Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions. > > Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as: > > **String.equalsIgnoreCase(String)** > > - Unicode-aware, locale-independent. > - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point. > - Limited: does not support 1:M mapping defined in Unicode case folding. > > **Character.toLowerCase(int) / Character.toUpperCase(int)** > > - Locale-independent, single code point only. > - No support for 1:M mappings. > > **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)** > > - Based on Unicode SpecialCasing.txt, supports 1:M mappings. > - Intended primarily for presentation/display, not structural case-insensitive matching. > - Requires full string conversion before comparison, which is less efficient and not intended for structural matching. > > **1:M mapping example, U+00DF (?)** > > - String.toUpperCase(Locale.ROOT, "?") ? "SS" > - Case folding produces "ss", matching Unicode caseless comparison rules. > > > jshell> "\u00df".equalsIgnoreCase("ss") > $22 ==> false > > jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss") > $24 ==> true > > > ### Motivation & Direction > > Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching. > > - Unicode-compliant **full** case folding. > - Simpler, stable and more efficient case-less matching without workarounds. > - Brings Java's string comparison handling in line with other programming languages/libraries. > > This PR proposes to introduce the following comparison methods in `String` class > > - boolean equalsFoldCase(String anotherString) > - int compareToFoldCase(String anotherString) > - Comparator UNICODE_CASEFOLD_ORDER > > These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required. > > *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string. > However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then passed into APIs where case-folding semantics are not appropriate. > > ### The New API > > > /** > * Compares thi... Xueming Shen has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains two commits: - Merge branch 'master' of https://git.openjdk.org/jdk into JDK-8365675 - 8365675: Add String Unicode Case-Folding Support to update api ------------- Changes: https://git.openjdk.org/jdk/pull/26892/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=26892&range=01 Stats: 1282 lines in 12 files changed: 1119 ins; 137 del; 26 mod Patch: https://git.openjdk.org/jdk/pull/26892.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/26892/head:pull/26892 PR: https://git.openjdk.org/jdk/pull/26892 From rriggs at openjdk.org Fri Oct 3 19:54:22 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Fri, 3 Oct 2025 19:54:22 GMT Subject: RFR: 8365675: Add String Unicode Case-Folding Support [v2] In-Reply-To: References: Message-ID: On Fri, 3 Oct 2025 19:41:20 GMT, Xueming Shen wrote: >> ### Summary >> >> Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions. >> >> Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as: >> >> **String.equalsIgnoreCase(String)** >> >> - Unicode-aware, locale-independent. >> - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point. >> - Limited: does not support 1:M mapping defined in Unicode case folding. >> >> **Character.toLowerCase(int) / Character.toUpperCase(int)** >> >> - Locale-independent, single code point only. >> - No support for 1:M mappings. >> >> **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)** >> >> - Based on Unicode SpecialCasing.txt, supports 1:M mappings. >> - Intended primarily for presentation/display, not structural case-insensitive matching. >> - Requires full string conversion before comparison, which is less efficient and not intended for structural matching. >> >> **1:M mapping example, U+00DF (?)** >> >> - String.toUpperCase(Locale.ROOT, "?") ? "SS" >> - Case folding produces "ss", matching Unicode caseless comparison rules. >> >> >> jshell> "\u00df".equalsIgnoreCase("ss") >> $22 ==> false >> >> jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss") >> $24 ==> true >> >> >> ### Motivation & Direction >> >> Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching. >> >> - Unicode-compliant **full** case folding. >> - Simpler, stable and more efficient case-less matching without workarounds. >> - Brings Java's string comparison handling in line with other programming languages/libraries. >> >> This PR proposes to introduce the following comparison methods in `String` class >> >> - boolean equalsFoldCase(String anotherString) >> - int compareToFoldCase(String anotherString) >> - Comparator UNICODE_CASEFOLD_ORDER >> >> These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required. >> >> *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string. >> However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then pass... > > Xueming Shen has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains two commits: > > - Merge branch 'master' of https://git.openjdk.org/jdk into JDK-8365675 > - 8365675: Add String Unicode Case-Folding Support > > to update api src/java.base/share/classes/jdk/internal/lang/CaseFolding.java.template line 1: > 1: /* We're going to need to find a more compact format for the data, individual 1 or 2 entry char arrays have a large overhead. Plus the map entries take a lot of space for the data and indexing. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/26892#discussion_r2403194785 From sherman at openjdk.org Fri Oct 3 19:54:23 2025 From: sherman at openjdk.org (Xueming Shen) Date: Fri, 3 Oct 2025 19:54:23 GMT Subject: Withdrawn: 8365675: Add String Unicode Case-Folding Support In-Reply-To: References: Message-ID: On Fri, 22 Aug 2025 03:50:03 GMT, Xueming Shen wrote: > ### Summary > > Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions. > > Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as: > > **String.equalsIgnoreCase(String)** > > - Unicode-aware, locale-independent. > - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point. > - Limited: does not support 1:M mapping defined in Unicode case folding. > > **Character.toLowerCase(int) / Character.toUpperCase(int)** > > - Locale-independent, single code point only. > - No support for 1:M mappings. > > **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)** > > - Based on Unicode SpecialCasing.txt, supports 1:M mappings. > - Intended primarily for presentation/display, not structural case-insensitive matching. > - Requires full string conversion before comparison, which is less efficient and not intended for structural matching. > > **1:M mapping example, U+00DF (?)** > > - String.toUpperCase(Locale.ROOT, "?") ? "SS" > - Case folding produces "ss", matching Unicode caseless comparison rules. > > > jshell> "\u00df".equalsIgnoreCase("ss") > $22 ==> false > > jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss") > $24 ==> true > > > ### Motivation & Direction > > Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching. > > - Unicode-compliant **full** case folding. > - Simpler, stable and more efficient case-less matching without workarounds. > - Brings Java's string comparison handling in line with other programming languages/libraries. > > This PR proposes to introduce the following comparison methods in `String` class > > - boolean equalsFoldCase(String anotherString) > - int compareToFoldCase(String anotherString) > - Comparator UNICODE_CASEFOLD_ORDER > > These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required. > > *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string. > However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then passed into APIs where case-folding semantics are not appropriate. > > ### The New API > > > /** > * Compares thi... This pull request has been closed without being integrated. ------------- PR: https://git.openjdk.org/jdk/pull/26892 From sherman at openjdk.org Fri Oct 3 20:09:21 2025 From: sherman at openjdk.org (Xueming Shen) Date: Fri, 3 Oct 2025 20:09:21 GMT Subject: RFR: 8365675: Add String Unicode Case-Folding Support Message-ID: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com> ### Summary Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions. Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as: **String.equalsIgnoreCase(String)** - Unicode-aware, locale-independent. - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point. - Limited: does not support 1:M mapping defined in Unicode case folding. **Character.toLowerCase(int) / Character.toUpperCase(int)** - Locale-independent, single code point only. - No support for 1:M mappings. **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)** - Based on Unicode SpecialCasing.txt, supports 1:M mappings. - Intended primarily for presentation/display, not structural case-insensitive matching. - Requires full string conversion before comparison, which is less efficient and not intended for structural matching. **1:M mapping example, U+00DF (?)** - String.toUpperCase(Locale.ROOT, "?") ? "SS" - Case folding produces "ss", matching Unicode caseless comparison rules. jshell> "\u00df".equalsIgnoreCase("ss") $22 ==> false jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss") $24 ==> true ### Motivation & Direction Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching. - Unicode-compliant **full** case folding. - Simpler, stable and more efficient case-less matching without workarounds. - Brings Java's string comparison handling in line with other programming languages/libraries. This PR proposes to introduce the following comparison methods in `String` class - boolean equalsFoldCase(String anotherString) - int compareToFoldCase(String anotherString) - Comparator UNICODE_CASEFOLD_ORDER These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required. *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string. However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then passed into APIs where case-folding semantics are not appropriate. ### The New API /** * Compares this {@code String} to another {@code String} for equality, * using Unicode case folding. Two strings are considered equal * by this method if their case-folded forms are identical. *

* Case folding is defined by the Unicode Standard in * CaseFolding.txt, * including 1:M mappings. For example, {@code "Ma?e".equalsFoldCase("MASSE")} * returns {@code true}, since the character {@code U+00DF} (sharp s) folds * to {@code "ss"}. *

* Case folding is locale-independent and language-neutral, unlike * locale-sensitive transformations such as {@link #toLowerCase()} or * {@link #toUpperCase()}. It is intended for caseless matching, * searching, and indexing. * * @apiNote * This method is the Unicode-compliant alternative to * {@link #equalsIgnoreCase(String)}. It implements full case folding as * defined by the Unicode Standard, which may differ from the simpler * per-character mapping performed by {@code equalsIgnoreCase}. * For example: *

{@snippet lang=java :
     * String a = "Ma?e";
     * String b = "MASSE";
     * boolean equalsFoldCase = a.equalsFoldCase(b);       // returns true
     * boolean equalsIgnoreCase = a.equalsIgnoreCase(b);   // returns false
     * }
* * @param anotherString * The {@code String} to compare this {@code String} against * * @return {@code true} if the given object is not {@code null} and represents * the same sequence of characters as this string under Unicode case * folding; {@code false} otherwise. * * @see #compareToFoldCase(String) * @see #equalsIgnoreCase(String) * @since 26 */ public boolean equalsFoldCase(String anotherString) /** * Compares two strings lexicographically using Unicode case folding. * This method returns an integer whose sign is that of calling {@code compareTo} * on the Unicode case folded version of the strings. Unicode Case folding * eliminates differences in case according to the Unicode Standard, using the * mappings defined in * CaseFolding.txt, * including 1:M mappings, such as {@code"?"} ? {@code }"ss"}. *

* Case folding is a locale-independent, language-neutral form of case mapping, * primarily intended for caseless matching. Unlike {@link #compareToIgnoreCase(String)}, * which applies a simpler locale-insensitive uppercase mapping. This method * follows the Unicode full case folding, providing stable and * consistent results across all environments. *

* Note that this method does not take locale into account, and may * produce results that differ from locale-sensitive ordering. Use * {@link java.text.Collator} for locale-sensitive comparison. * * @apiNote * This method is the Unicode-compliant alternative to * {@link #compareToIgnoreCase(String)}. It implements the full case folding * as defined by the Unicode Standard, which may differ from the simpler * per-character mapping performed by {@code compareToIgnoreCase}. * For example: *

{@snippet lang=java :
     * String a = "Ma?e";
     * String b = "MASSE";
     * int cmpFoldCase = a.compareToFoldCase(b);     // returns 0
     * int cmpIgnoreCase = a.compareToIgnoreCase(b); // returns > 0
     * }
* * @param str the {@code String} to be compared. * @return a negative integer, zero, or a positive integer as the specified * String is greater than, equal to, or less than this String, * ignoring case considerations by case folding. * @see #equalsFoldCase(String) * @see #compareToIgnoreCase(String) * @see java.text.Collator * @since 26 */ public int compareToFoldCase(String str) /** * A Comparator that orders {@code String} objects as by * {@link #compareToFoldCase(String) compareToFoldCase()}. * * @see #compareToFoldCase(String) * @since 26 */ public static final Comparator UNICODE_CASEFOLD_ORDER; ### Usage Examples Sharp s (U+00DF) case-folds to "ss" "stra?e".equalsIgnoreCase("strasse"); // false "stra?e".compareToIgnoreCase("strasse"); // != 0 "stra?e".equalsFoldCase("strasse"); // true ### Performance The JMH microbenchmark StringCompareToIgnoreCase has been updated to compare performance of compareToFoldCase with the existing compareToIgnoreCase(). Benchmark Mode Cnt Score Error Units StringCompareToIgnoreCase.asciiGreekLower avgt 15 20.195 ? 0.300 ns/op StringCompareToIgnoreCase.asciiGreekLowerCF avgt 15 11.051 ? 0.254 ns/op StringCompareToIgnoreCase.asciiGreekUpperLower avgt 15 6.035 ? 0.047 ns/op StringCompareToIgnoreCase.asciiGreekUpperLowerCF avgt 15 14.786 ? 0.382 ns/op StringCompareToIgnoreCase.asciiLower avgt 15 17.688 ? 1.396 ns/op StringCompareToIgnoreCase.asciiLowerCF avgt 15 44.552 ? 0.155 ns/op StringCompareToIgnoreCase.asciiUpperLower avgt 15 13.069 ? 0.487 ns/op StringCompareToIgnoreCase.asciiUpperLowerCF avgt 15 58.684 ? 0.274 ns/op StringCompareToIgnoreCase.greekLower avgt 15 20.642 ? 0.082 ns/op StringCompareToIgnoreCase.greekLowerCF avgt 15 7.255 ? 0.271 ns/op StringCompareToIgnoreCase.greekUpperLower avgt 15 5.737 ? 0.013 ns/op StringCompareToIgnoreCase.greekUpperLowerCF avgt 15 11.100 ? 1.147 ns/op StringCompareToIgnoreCase.lower avgt 15 20.192 ? 0.044 ns/op StringCompareToIgnoreCase.lowerrCF avgt 15 11.257 ? 0.259 ns/op StringCompareToIgnoreCase.supLower avgt 15 54.801 ? 0.415 ns/op StringCompareToIgnoreCase.supLowerCF avgt 15 15.207 ? 0.418 ns/op StringCompareToIgnoreCase.supUpperLower avgt 15 14.431 ? 0.188 ns/op StringCompareToIgnoreCase.supUpperLowerCF avgt 15 19.149 ? 0.985 ns/op StringCompareToIgnoreCase.upperLower avgt 15 5.650 ? 0.051 ns/op StringCompareToIgnoreCase.upperLowerCF avgt 15 14.338 ? 0.352 ns/op StringCompareToIgnoreCase.utf16SubLower avgt 15 14.774 ? 0.200 ns/op StringCompareToIgnoreCase.utf16SubLowerCF avgt 15 2.669 ? 0.041 ns/op StringCompareToIgnoreCase.utf16SupUpperLower avgt 15 16.250 ? 0.099 ns/op StringCompareToIgnoreCase.utf16SupUpperLowerCF avgt 15 11.524 ? 0.327 ns/op ### Refs [Unicode Standard 5.18.4 Caseless Matching](https://www.unicode.org/versions/latest/core-spec/chapter-5/#G21790) [Unicode? Standard Annex #44: 5.6 Case and Case Mapping](https://www.unicode.org/reports/tr44/#Casemapping) [Unicode Technical Standard #18: Unicode Regular Expressions RL1.5: Simple Loose Matches](https://www.unicode.org/reports/tr18/#Simple_Loose_Matches) [Unicode SpecialCasing.txt](https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt) [Unicode CaseFolding.txt](https://www.unicode.org/Public/UCD/latest/ucd/CaseFolding.txt) ### Other Languages **Python string.casefold()** The str.casefold() method in Python returns a casefolded version of a string. Casefolding is a more aggressive form of lowercasing, designed to remove all case distinctions in a string, particularly for the purpose of caseless string comparisons. **Perl?s fc()** Returns the casefolded version of EXPR. This is the internal function implementing the \F escape in double-quoted strings. Casefolding is the process of mapping strings to a form where case differences are erased; comparing two strings in their casefolded form is effectively a way of asking if two strings are equal, regardless of case. Perl only implements the full form of casefolding, but you can access the simple folds using "casefold()" in Unicode::UCD] ad "prop_invmap()" in Unicode::UCD]. **ICU4J UCharacter.foldCase (Java)** Purpose: Provides extensions to the standard Java Character class, including support for more Unicode properties and handling of supplementary characters (code points beyond U+FFFF). Method Signature (String based): public static String foldCase(String str, int options) Method Signature (CharSequence & Appendable based): public static A foldCase(CharSequence src, A dest, int options, Edits edits) Key Features: Case Folding: Converts a string to its case-folded equivalent. Locale Independent: Case folding in UCharacter.foldCase is generally not dependent on locale settings. Context Insensitive: The mapping of a character is not affected by surrounding characters. Turkic Option: An option exists to include or exclude special mappings for Turkish/Azerbaijani text. Result Length: The resulting string can be longer or shorter than the original. Edits Recording: Allows for recording of edits for index mapping, styled text, and getting only changes. **u_strFoldCase (C/C++)** A lower-level C API function for case folding a string. Case Folding Options: Similar options as UCharacter.foldCase for controlling case folding behavior. Availability: Found in the ustring.h and unistr.h headers in the ICU4C library. ------------- Commit messages: - Merge branch 'master' of https://git.openjdk.org/jdk into JDK-8365675 - 8365675: Add String Unicode Case-Folding Support Changes: https://git.openjdk.org/jdk/pull/27628/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27628&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8365675 Stats: 1282 lines in 12 files changed: 1119 ins; 137 del; 26 mod Patch: https://git.openjdk.org/jdk/pull/27628.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27628/head:pull/27628 PR: https://git.openjdk.org/jdk/pull/27628 From duke at openjdk.org Sun Oct 5 00:38:55 2025 From: duke at openjdk.org (Tatsunori Uchino) Date: Sun, 5 Oct 2025 00:38:55 GMT Subject: RFR: 8364007: Add no-argument codePointCount method to CharSequence and String [v3] In-Reply-To: References: Message-ID: On Sat, 26 Jul 2025 10:10:40 GMT, Tatsunori Uchino wrote: >> Adds `codePointCount()` overloads to `String`, `Character`, `(Abstract)StringBuilder`, and `StringBuffer` to make it possible to conveniently retrieve the length of a string as code points without extra boundary checks. >> >> >> if (superTremendouslyLongExpressionYieldingAString().codePointCount() > limit) { >> throw new Exception("exceeding length"); >> } >> >> >> Is a CSR required to this change? > > Tatsunori Uchino has updated the pull request incrementally with four additional commits since the last revision: > > - Update `@bug` in correct file > - Add default implementation on codePointCount in CharSequence > - Update `@bug` entries in test class doc comments > - Discard changes on code whose form is not `str.codePointCount(0, str.length())` > Character.codePointCount(CharSequence) > CharSequence.codePointCount I think that the problem is which of both should be _canonical_ (the other is just a call for the canonical one). public class Character { public static int codePointCount(CharSequence s) { return s.codePointCount(); } } I expect that an inline expansion is applied there. > Do we need codePointCount(int start, int end) in CharSequence too? IMO it is fine either way. It is OK to postpone/defer it. ------------- PR Comment: https://git.openjdk.org/jdk/pull/26461#issuecomment-3368632586 From prappo at openjdk.org Mon Oct 6 11:32:51 2025 From: prappo at openjdk.org (Pavel Rappo) Date: Mon, 6 Oct 2025 11:32:51 GMT Subject: RFR: 8366829: Add java.time.Duration constants MIN and MAX [v3] In-Reply-To: References: Message-ID: On Fri, 3 Oct 2025 09:50:23 GMT, Pavel Rappo wrote: >> We have [recently discussed][] a possibility of adding the `Duration.MIN` and `Duration.MAX` constants. Can we now start implementation? If and when we are in agreement on this PR, I will file a CSR. >> >> I drafted a minimal specification and added some tests. I tried to phrase the spec for `Duration.MIN` in a way that makes it clear that `Duration.MIN` is the most negative value and not the least positive. >> >> [recently discussed]: https://mail.openjdk.org/pipermail/core-libs-dev/2025-September/151098.html > > Pavel Rappo has updated the pull request incrementally with one additional commit since the last revision: > > Respond to feedback > > Apply Stephen's suggestion on wording, although modified. Thanks for the reviews. I'll draft the CSR shortly. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27534#issuecomment-3371166113 From ihse at openjdk.org Mon Oct 6 12:38:41 2025 From: ihse at openjdk.org (Magnus Ihse Bursie) Date: Mon, 6 Oct 2025 12:38:41 GMT Subject: RFR: 8365675: Add String Unicode Case-Folding Support In-Reply-To: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com> References: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com> Message-ID: On Fri, 3 Oct 2025 19:56:22 GMT, Xueming Shen wrote: > ### Summary > > Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions. > > Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as: > > **String.equalsIgnoreCase(String)** > > - Unicode-aware, locale-independent. > - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point. > - Limited: does not support 1:M mapping defined in Unicode case folding. > > **Character.toLowerCase(int) / Character.toUpperCase(int)** > > - Locale-independent, single code point only. > - No support for 1:M mappings. > > **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)** > > - Based on Unicode SpecialCasing.txt, supports 1:M mappings. > - Intended primarily for presentation/display, not structural case-insensitive matching. > - Requires full string conversion before comparison, which is less efficient and not intended for structural matching. > > **1:M mapping example, U+00DF (?)** > > - String.toUpperCase(Locale.ROOT, "?") ? "SS" > - Case folding produces "ss", matching Unicode caseless comparison rules. > > > jshell> "\u00df".equalsIgnoreCase("ss") > $22 ==> false > > jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss") > $24 ==> true > > > ### Motivation & Direction > > Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching. > > - Unicode-compliant **full** case folding. > - Simpler, stable and more efficient case-less matching without workarounds. > - Brings Java's string comparison handling in line with other programming languages/libraries. > > This PR proposes to introduce the following comparison methods in `String` class > > - boolean equalsFoldCase(String anotherString) > - int compareToFoldCase(String anotherString) > - Comparator UNICODE_CASEFOLD_ORDER > > These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required. > > *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string. > However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then passed into APIs where case-folding semantics are not appropriate. > > ### The New API > > > /** > * Compares thi... Build changes look fine. ------------- Marked as reviewed by ihse (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27628#pullrequestreview-3304307032 From scolebourne at openjdk.org Mon Oct 6 19:07:48 2025 From: scolebourne at openjdk.org (Stephen Colebourne) Date: Mon, 6 Oct 2025 19:07:48 GMT Subject: RFR: 8366829: Add java.time.Duration constants MIN and MAX [v3] In-Reply-To: References: Message-ID: On Fri, 3 Oct 2025 09:50:23 GMT, Pavel Rappo wrote: >> We have [recently discussed][] a possibility of adding the `Duration.MIN` and `Duration.MAX` constants. Can we now start implementation? If and when we are in agreement on this PR, I will file a CSR. >> >> I drafted a minimal specification and added some tests. I tried to phrase the spec for `Duration.MIN` in a way that makes it clear that `Duration.MIN` is the most negative value and not the least positive. >> >> [recently discussed]: https://mail.openjdk.org/pipermail/core-libs-dev/2025-September/151098.html > > Pavel Rappo has updated the pull request incrementally with one additional commit since the last revision: > > Respond to feedback > > Apply Stephen's suggestion on wording, although modified. Marked as reviewed by scolebourne (Author). ------------- PR Review: https://git.openjdk.org/jdk/pull/27534#pullrequestreview-3306703205 From sherman at openjdk.org Mon Oct 6 20:59:48 2025 From: sherman at openjdk.org (Xueming Shen) Date: Mon, 6 Oct 2025 20:59:48 GMT Subject: RFR: 8368845: x-IBM930 uses incorrect character for Hex 42 60 [v2] In-Reply-To: References: <0Ep8UN3_bJ-nR9RCNIUaRA7flGGV3khNSjstui2ijRk=.d3eb41c7-1bae-4916-9c80-876d5912724f@github.com> Message-ID: On Wed, 1 Oct 2025 21:06:19 GMT, Naoto Sato wrote: >> Fixing a charset en/decoder for x-IBM930. There was a "temporary" mapping for the said code point for the backward compatibility (as of JDK7). Since the issue requests the "correct" mapping, I believe we can replace the temporary one with the correct mapping. > > Naoto Sato has updated the pull request incrementally with one additional commit since the last revision: > > added bugid to the tests looks good. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27594#issuecomment-3374089434 From naoto at openjdk.org Mon Oct 6 21:43:21 2025 From: naoto at openjdk.org (Naoto Sato) Date: Mon, 6 Oct 2025 21:43:21 GMT Subject: RFR: 8369184: SimpleTimeZone equals() Returns True for Unequal Instances with Different hashCode Values Message-ID: Fixing the equals/hashCode contract in the SimpleTimeZone class. The current implementation includes DST rule fields in hash code computation even for zones that do not observe DST, while equals() always considers them. Also correcting the example code in the class description, where it used 20-year-old obsolete "America/Los_Angeles" rule. ------------- Commit messages: - initial commit Changes: https://git.openjdk.org/jdk/pull/27660/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27660&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8369184 Stats: 96 lines in 2 files changed: 89 ins; 0 del; 7 mod Patch: https://git.openjdk.org/jdk/pull/27660.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27660/head:pull/27660 PR: https://git.openjdk.org/jdk/pull/27660 From naoto at openjdk.org Mon Oct 6 21:49:31 2025 From: naoto at openjdk.org (Naoto Sato) Date: Mon, 6 Oct 2025 21:49:31 GMT Subject: RFR: 8369184: SimpleTimeZone equals() Returns True for Unequal Instances with Different hashCode Values [v2] In-Reply-To: References: Message-ID: > Fixing the equals/hashCode contract in the SimpleTimeZone class. The current implementation includes DST rule fields in hash code computation even for zones that do not observe DST, while equals() always considers them. Also correcting the example code in the class description, where it used 20-year-old obsolete "America/Los_Angeles" rule. Naoto Sato has updated the pull request incrementally with one additional commit since the last revision: fixed typo ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27660/files - new: https://git.openjdk.org/jdk/pull/27660/files/ad1e8be6..a2c988d8 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27660&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27660&range=00-01 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/27660.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27660/head:pull/27660 PR: https://git.openjdk.org/jdk/pull/27660 From sherman at openjdk.org Mon Oct 6 22:12:45 2025 From: sherman at openjdk.org (Xueming Shen) Date: Mon, 6 Oct 2025 22:12:45 GMT Subject: RFR: 8368845: x-IBM930 uses incorrect character for Hex 42 60 [v2] In-Reply-To: References: <0Ep8UN3_bJ-nR9RCNIUaRA7flGGV3khNSjstui2ijRk=.d3eb41c7-1bae-4916-9c80-876d5912724f@github.com> Message-ID: On Wed, 1 Oct 2025 21:06:19 GMT, Naoto Sato wrote: >> Fixing a charset en/decoder for x-IBM930. There was a "temporary" mapping for the said code point for the backward compatibility (as of JDK7). Since the issue requests the "correct" mapping, I believe we can replace the temporary one with the correct mapping. > > Naoto Sato has updated the pull request incrementally with one additional commit since the last revision: > > added bugid to the tests Looks good. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27594#issuecomment-3374439736 From sherman at openjdk.org Mon Oct 6 22:16:46 2025 From: sherman at openjdk.org (Xueming Shen) Date: Mon, 6 Oct 2025 22:16:46 GMT Subject: RFR: 8368845: x-IBM930 uses incorrect character for Hex 42 60 [v2] In-Reply-To: References: <0Ep8UN3_bJ-nR9RCNIUaRA7flGGV3khNSjstui2ijRk=.d3eb41c7-1bae-4916-9c80-876d5912724f@github.com> Message-ID: On Wed, 1 Oct 2025 21:06:19 GMT, Naoto Sato wrote: >> Fixing a charset en/decoder for x-IBM930. There was a "temporary" mapping for the said code point for the backward compatibility (as of JDK7). Since the issue requests the "correct" mapping, I believe we can replace the temporary one with the correct mapping. > > Naoto Sato has updated the pull request incrementally with one additional commit since the last revision: > > added bugid to the tests Looks good. ------------- Marked as reviewed by sherman (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27594#pullrequestreview-3307679853 From rriggs at openjdk.org Tue Oct 7 13:21:28 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Tue, 7 Oct 2025 13:21:28 GMT Subject: RFR: 8368845: x-IBM930 uses incorrect character for Hex 42 60 [v2] In-Reply-To: References: <0Ep8UN3_bJ-nR9RCNIUaRA7flGGV3khNSjstui2ijRk=.d3eb41c7-1bae-4916-9c80-876d5912724f@github.com> Message-ID: On Wed, 1 Oct 2025 21:06:19 GMT, Naoto Sato wrote: >> Fixing a charset en/decoder for x-IBM930. There was a "temporary" mapping for the said code point for the backward compatibility (as of JDK7). Since the issue requests the "correct" mapping, I believe we can replace the temporary one with the correct mapping. > > Naoto Sato has updated the pull request incrementally with one additional commit since the last revision: > > added bugid to the tests LGTM ------------- Marked as reviewed by rriggs (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27594#pullrequestreview-3310084423 From iris at openjdk.org Tue Oct 7 15:48:07 2025 From: iris at openjdk.org (Iris Clark) Date: Tue, 7 Oct 2025 15:48:07 GMT Subject: RFR: 8368845: x-IBM930 uses incorrect character for Hex 42 60 [v2] In-Reply-To: References: <0Ep8UN3_bJ-nR9RCNIUaRA7flGGV3khNSjstui2ijRk=.d3eb41c7-1bae-4916-9c80-876d5912724f@github.com> Message-ID: On Wed, 1 Oct 2025 21:06:19 GMT, Naoto Sato wrote: >> Fixing a charset en/decoder for x-IBM930. There was a "temporary" mapping for the said code point for the backward compatibility (as of JDK7). Since the issue requests the "correct" mapping, I believe we can replace the temporary one with the correct mapping. > > Naoto Sato has updated the pull request incrementally with one additional commit since the last revision: > > added bugid to the tests Marked as reviewed by iris (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27594#pullrequestreview-3310763073 From naoto at openjdk.org Tue Oct 7 17:23:48 2025 From: naoto at openjdk.org (Naoto Sato) Date: Tue, 7 Oct 2025 17:23:48 GMT Subject: RFR: 8368845: x-IBM930 uses incorrect character for Hex 42 60 [v2] In-Reply-To: References: <0Ep8UN3_bJ-nR9RCNIUaRA7flGGV3khNSjstui2ijRk=.d3eb41c7-1bae-4916-9c80-876d5912724f@github.com> Message-ID: On Wed, 1 Oct 2025 21:06:19 GMT, Naoto Sato wrote: >> Fixing a charset en/decoder for x-IBM930. There was a "temporary" mapping for the said code point for the backward compatibility (as of JDK7). Since the issue requests the "correct" mapping, I believe we can replace the temporary one with the correct mapping. > > Naoto Sato has updated the pull request incrementally with one additional commit since the last revision: > > added bugid to the tests Thanks for the reviews! ------------- PR Comment: https://git.openjdk.org/jdk/pull/27594#issuecomment-3377830143 From naoto at openjdk.org Tue Oct 7 17:23:50 2025 From: naoto at openjdk.org (Naoto Sato) Date: Tue, 7 Oct 2025 17:23:50 GMT Subject: Integrated: 8368845: x-IBM930 uses incorrect character for Hex 42 60 In-Reply-To: <0Ep8UN3_bJ-nR9RCNIUaRA7flGGV3khNSjstui2ijRk=.d3eb41c7-1bae-4916-9c80-876d5912724f@github.com> References: <0Ep8UN3_bJ-nR9RCNIUaRA7flGGV3khNSjstui2ijRk=.d3eb41c7-1bae-4916-9c80-876d5912724f@github.com> Message-ID: On Wed, 1 Oct 2025 19:50:49 GMT, Naoto Sato wrote: > Fixing a charset en/decoder for x-IBM930. There was a "temporary" mapping for the said code point for the backward compatibility (as of JDK7). Since the issue requests the "correct" mapping, I believe we can replace the temporary one with the correct mapping. This pull request has now been integrated. Changeset: 6b316262 Author: Naoto Sato URL: https://git.openjdk.org/jdk/commit/6b3162620bd808227ec7b4331ae6fc32ceb909e8 Stats: 22 lines in 6 files changed: 1 ins; 13 del; 8 mod 8368845: x-IBM930 uses incorrect character for Hex 42 60 Reviewed-by: sherman, rriggs, iris ------------- PR: https://git.openjdk.org/jdk/pull/27594 From naoto at openjdk.org Tue Oct 7 18:41:09 2025 From: naoto at openjdk.org (Naoto Sato) Date: Tue, 7 Oct 2025 18:41:09 GMT Subject: RFR: 8365675: Add String Unicode Case-Folding Support In-Reply-To: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com> References: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com> Message-ID: <3joVVX55ZEto_x9dhTVpYgMGzPtL8tdNNvZxiBmsuHE=.42d5f21c-64b4-4547-99e1-f2a3af104272@github.com> On Fri, 3 Oct 2025 19:56:22 GMT, Xueming Shen wrote: > ### Summary > > Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions. > > Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as: > > **String.equalsIgnoreCase(String)** > > - Unicode-aware, locale-independent. > - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point. > - Limited: does not support 1:M mapping defined in Unicode case folding. > > **Character.toLowerCase(int) / Character.toUpperCase(int)** > > - Locale-independent, single code point only. > - No support for 1:M mappings. > > **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)** > > - Based on Unicode SpecialCasing.txt, supports 1:M mappings. > - Intended primarily for presentation/display, not structural case-insensitive matching. > - Requires full string conversion before comparison, which is less efficient and not intended for structural matching. > > **1:M mapping example, U+00DF (?)** > > - String.toUpperCase(Locale.ROOT, "?") ? "SS" > - Case folding produces "ss", matching Unicode caseless comparison rules. > > > jshell> "\u00df".equalsIgnoreCase("ss") > $22 ==> false > > jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss") > $24 ==> true > > > ### Motivation & Direction > > Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching. > > - Unicode-compliant **full** case folding. > - Simpler, stable and more efficient case-less matching without workarounds. > - Brings Java's string comparison handling in line with other programming languages/libraries. > > This PR proposes to introduce the following comparison methods in `String` class > > - boolean equalsFoldCase(String anotherString) > - int compareToFoldCase(String anotherString) > - Comparator UNICODE_CASEFOLD_ORDER > > These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required. > > *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string. > However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then passed into APIs where case-folding semantics are not appropriate. > > ### The New API > > > /** > * Compares thi... While working on Unicode 17 upgrade, I noticed that they changed the example from "MASSE"/"Ma?e" to "FUSS"/"Fu?" (https://www.unicode.org/L2/L2025/25085.htm#183-A59), so you might want to switch them as well ------------- PR Comment: https://git.openjdk.org/jdk/pull/27628#issuecomment-3378153999 From jlu at openjdk.org Tue Oct 7 19:00:47 2025 From: jlu at openjdk.org (Justin Lu) Date: Tue, 7 Oct 2025 19:00:47 GMT Subject: RFR: 8369184: SimpleTimeZone equals() Returns True for Unequal Instances with Different hashCode Values [v2] In-Reply-To: References: Message-ID: On Mon, 6 Oct 2025 21:49:31 GMT, Naoto Sato wrote: >> Fixing the equals/hashCode contract in the SimpleTimeZone class. The current implementation includes DST rule fields in hash code computation even for zones that do not observe DST, while equals() always considers them. Also correcting the example code in the class description, where it used 20-year-old obsolete "America/Los_Angeles" rule. > > Naoto Sato has updated the pull request incrementally with one additional commit since the last revision: > > fixed typo LGTM src/java.base/share/classes/java/util/SimpleTimeZone.java line 871: > 869: public int hashCode() > 870: { > 871: int hash = 31 * getID().hashCode() + rawOffset; int hash = Objects.hash(getID(), rawOffset, useDaylight); return !useDaylight ? hash : 31 * hash + Objects.hash( startMonth, startDay, startDayOfWeek, startTime, endMonth, endDay, endDayOfWeek, endTime); Seems reasonable to use `Objects.hash` here. Could save some lines if wanted? test/jdk/java/util/TimeZone/SimpleTimeZoneHashCodeTest.java line 1: > 1: /* Include _equals_ in the test name as well? Perhaps _HashCodeEqualsTest_ or something along those lines. ------------- Marked as reviewed by jlu (Committer). PR Review: https://git.openjdk.org/jdk/pull/27660#pullrequestreview-3311435895 PR Review Comment: https://git.openjdk.org/jdk/pull/27660#discussion_r2411594933 PR Review Comment: https://git.openjdk.org/jdk/pull/27660#discussion_r2411564566 From naoto at openjdk.org Tue Oct 7 20:43:23 2025 From: naoto at openjdk.org (Naoto Sato) Date: Tue, 7 Oct 2025 20:43:23 GMT Subject: RFR: 8369184: SimpleTimeZone equals() Returns True for Unequal Instances with Different hashCode Values [v2] In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 18:54:34 GMT, Justin Lu wrote: >> Naoto Sato has updated the pull request incrementally with one additional commit since the last revision: >> >> fixed typo > > src/java.base/share/classes/java/util/SimpleTimeZone.java line 871: > >> 869: public int hashCode() >> 870: { >> 871: int hash = 31 * getID().hashCode() + rawOffset; > > int hash = Objects.hash(getID(), rawOffset, useDaylight); > return !useDaylight ? hash : 31 * hash + Objects.hash( > startMonth, startDay, startDayOfWeek, startTime, endMonth, endDay, endDayOfWeek, endTime); > > > Seems reasonable to use `Objects.hash` here. Could save some lines if wanted? Initially, I thought so, but decided to avoid extra array allocation/copy. But on second thought, the instances of this class would seldom be used as hash keys so not that performance critical. Either way is fine with me > test/jdk/java/util/TimeZone/SimpleTimeZoneEqualsHashCodeTest.java line 1: > >> (failed to retrieve contents of file, check the PR for context) > Include _equals_ in the test name as well? Perhaps _HashCodeEqualsTest_ or something along those lines. Renamed. I left `SimpleTimeZone` as the test is specific for this class. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27660#discussion_r2411787045 PR Review Comment: https://git.openjdk.org/jdk/pull/27660#discussion_r2411778576 From naoto at openjdk.org Tue Oct 7 20:43:20 2025 From: naoto at openjdk.org (Naoto Sato) Date: Tue, 7 Oct 2025 20:43:20 GMT Subject: RFR: 8369184: SimpleTimeZone equals() Returns True for Unequal Instances with Different hashCode Values [v3] In-Reply-To: References: Message-ID: > Fixing the equals/hashCode contract in the SimpleTimeZone class. The current implementation includes DST rule fields in hash code computation even for zones that do not observe DST, while equals() always considers them. Also correcting the example code in the class description, where it used 20-year-old obsolete "America/Los_Angeles" rule. Naoto Sato has updated the pull request incrementally with one additional commit since the last revision: Address review comments ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27660/files - new: https://git.openjdk.org/jdk/pull/27660/files/a2c988d8..aafdf18b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27660&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27660&range=01-02 Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/27660.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27660/head:pull/27660 PR: https://git.openjdk.org/jdk/pull/27660 From rriggs at openjdk.org Tue Oct 7 22:25:08 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Tue, 7 Oct 2025 22:25:08 GMT Subject: RFR: 8365675: Add String Unicode Case-Folding Support In-Reply-To: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com> References: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com> Message-ID: On Fri, 3 Oct 2025 19:56:22 GMT, Xueming Shen wrote: > ### Summary > > Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions. > > Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as: > > **String.equalsIgnoreCase(String)** > > - Unicode-aware, locale-independent. > - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point. > - Limited: does not support 1:M mapping defined in Unicode case folding. > > **Character.toLowerCase(int) / Character.toUpperCase(int)** > > - Locale-independent, single code point only. > - No support for 1:M mappings. > > **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)** > > - Based on Unicode SpecialCasing.txt, supports 1:M mappings. > - Intended primarily for presentation/display, not structural case-insensitive matching. > - Requires full string conversion before comparison, which is less efficient and not intended for structural matching. > > **1:M mapping example, U+00DF (?)** > > - String.toUpperCase(Locale.ROOT, "?") ? "SS" > - Case folding produces "ss", matching Unicode caseless comparison rules. > > > jshell> "\u00df".equalsIgnoreCase("ss") > $22 ==> false > > jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss") > $24 ==> true > > > ### Motivation & Direction > > Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching. > > - Unicode-compliant **full** case folding. > - Simpler, stable and more efficient case-less matching without workarounds. > - Brings Java's string comparison handling in line with other programming languages/libraries. > > This PR proposes to introduce the following comparison methods in `String` class > > - boolean equalsFoldCase(String anotherString) > - int compareToFoldCase(String anotherString) > - Comparator UNICODE_CASEFOLD_ORDER > > These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required. > > *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string. > However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then passed into APIs where case-folding semantics are not appropriate. > > ### The New API > > > /** > * Compares thi... The API looks good. Is the performance comparable to equalsIgnoreCase? src/java.base/share/classes/java/lang/StringLatin1.java line 194: > 192: char[] folded2 = null; > 193: int k1 = 0, k2 = 0, fk1 = 0, fk2 = 0; > 194: while ((k1 < len1 || folded1 != null && fk1 < folded1.length) && Many suggestions come to mind here on the algorithm, to optimize performance. For example, many strings will have identical prefixes. Using Arrays.mismatch could quickly skip over the identical prefix. Consider using code points (or a long, packing 4 chars) for the folded replacements, to avoid having to step through chars in char arrays. CaseFolding.foldIfDefined could return the full expansion as a long. It may be profitable to use Arrays.mismatch again after expanded characters are determined to be equal. Take another look at the data structure storing and doing the lookup of foldIfDefined both to increase the lookup performance. src/java.base/share/classes/jdk/internal/lang/CaseFolding.java.template line 230: > 228: private static class CaseFoldingEntry { > 229: final int cp; > 230: final char[] folding; Consider storing the folding as a int or long directly to avoid the overhead of small char arrays. Arrange to be able to compare the whole replacement with another codePoint, etc. src/java.base/share/classes/jdk/internal/lang/CaseFolding.java.template line 280: > 278: } > 279: > 280: private void add(CaseFoldingEntry entry) { CDS can map whole objects/data structures into the heap; consider how to make this data structure so it can be mapped and not re-computed each startup. ------------- PR Review: https://git.openjdk.org/jdk/pull/27628#pullrequestreview-3312084027 PR Review Comment: https://git.openjdk.org/jdk/pull/27628#discussion_r2412043131 PR Review Comment: https://git.openjdk.org/jdk/pull/27628#discussion_r2412060747 PR Review Comment: https://git.openjdk.org/jdk/pull/27628#discussion_r2412062604 From jlu at openjdk.org Tue Oct 7 23:52:37 2025 From: jlu at openjdk.org (Justin Lu) Date: Tue, 7 Oct 2025 23:52:37 GMT Subject: RFR: 8369050: DecimalFormat Rounding Errors for Ties Torwards 1 in LSD or 0 Message-ID: Please review this PR which corrects a rounding error for DecimalFormat on tie cases when the maximum fraction digits allowed is one less than the position of the first significant digit in the double rounded. For example, rounding a value such as 0.0005 to a maximum of 3 fractional digits. In order to get the correct `count` value, we must strip the trailing zeros prior to the check to ensure we have the correct value of `count` = 1 so that we can go down the _Rounding position is the last index_ case which properly checks if the String double was already rounded or is exact from its true decimal form. ------------- Commit messages: - small test changes - init Changes: https://git.openjdk.org/jdk/pull/27681/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27681&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8369050 Stats: 95 lines in 3 files changed: 88 ins; 5 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/27681.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27681/head:pull/27681 PR: https://git.openjdk.org/jdk/pull/27681 From jlu at openjdk.org Tue Oct 7 23:52:39 2025 From: jlu at openjdk.org (Justin Lu) Date: Tue, 7 Oct 2025 23:52:39 GMT Subject: RFR: 8369050: DecimalFormat Rounding Errors for Ties Torwards 1 in LSD or 0 In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 23:19:28 GMT, Justin Lu wrote: > Please review this PR which corrects a rounding error for DecimalFormat on tie cases when the maximum fraction digits allowed is one less than the position of the first significant digit in the double rounded. For example, rounding a value such as 0.0005 to a maximum of 3 fractional digits. In order to get the correct `count` value, we must strip the trailing zeros prior to the check to ensure we have the correct value of `count` = 1 so that we can go down the _Rounding position is the last index_ case which properly checks if the String double was already rounded or is exact from its true decimal form. For some history, this bug is long-standing, but has taken different forms after recent changes to DigitList. DigitList, when handling the specific case as mentioned in the summary statement returns a faulty value due to an incorrect value of `count`. DigitList used to parse its own `count` value, but was recently changed in [JDK-8367324](https://bugs.openjdk.org/browse/JDK-8367324) to retrieve `count`from `FloatingDecimal`. Consider the double `0.00005` rounded to 4 fractional digits, `count` prior to JDK-8367324 would be calculated as 2 while it is now calculated as 17 due to the implementation differences. Thus, when handling the following case, } else if (-decimalAt == maximumDigits) { // If we round 0.0009 to 3 fractional digits, then we have to // create a new one digit in the least significant location. if (shouldRoundUp(0, roundedUp, valueExactAsDecimal)) { count = 1; ++decimalAt; digits[0] = '1'; } else { For both `count` values, `if (maximumDigits == (count - 1))` is erroneously evaluated in `shouldRoundUp` under the HALF_* cases and instead falls under the _Rounding position is not the last index_ case. Notice that before JDK-8367324, `count` was still being read **incorrectly** as 2 (for fractional doubles in exponential form). However, the behavioral differences had not been observed, since the HALF_UP/DOWN cases prior to https://bugs.openjdk.org/browse/JDK-8314169 could return the right values by chance when going down the wrong path. test/jdk/java/text/Format/DecimalFormat/RoundingToLSDTieTest.java line 1: > 1: /* I considered adding the tests in this file under _TieRoundingTest_, but did not do so to make review easier since JUnit could be used for the test in this PR. (_TieRoundingTest_ is old and does not use JUnit.) Will consider updating _TieRoundingTest_ to use JUnit and merging the tests in this PR under it in a separate issue. test/jdk/java/text/Format/NumberFormat/NumberRegression.java line 1779: > 1777: "0%", "0%", "1%", "1%", "1%", > 1778: "0", "2", "0.2", "0.6", "0.04", > 1779: "0.04", "0.001", "0.002", This test is checking that `.0005` rounded to 3 digits is "0.000" under HALF_EVEN. This is wrong. See, `new BigDecimal(0.0005) ==> 0.0005000000000000000104083408558608425664715468883514404296875`. Resolving the bug in this PR requires fixing this incorrect test case. From the JDK-4241880 issue, it seems this case may have been put in to "document the incorrect but actual behavior". ------------- PR Comment: https://git.openjdk.org/jdk/pull/27681#issuecomment-3379027299 PR Review Comment: https://git.openjdk.org/jdk/pull/27681#discussion_r2412168905 PR Review Comment: https://git.openjdk.org/jdk/pull/27681#discussion_r2412167812 From sherman at openjdk.org Wed Oct 8 00:33:20 2025 From: sherman at openjdk.org (Xueming Shen) Date: Wed, 8 Oct 2025 00:33:20 GMT Subject: RFR: 8365675: Add String Unicode Case-Folding Support [v2] In-Reply-To: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com> References: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com> Message-ID: > ### Summary > > Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions. > > Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as: > > **String.equalsIgnoreCase(String)** > > - Unicode-aware, locale-independent. > - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point. > - Limited: does not support 1:M mapping defined in Unicode case folding. > > **Character.toLowerCase(int) / Character.toUpperCase(int)** > > - Locale-independent, single code point only. > - No support for 1:M mappings. > > **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)** > > - Based on Unicode SpecialCasing.txt, supports 1:M mappings. > - Intended primarily for presentation/display, not structural case-insensitive matching. > - Requires full string conversion before comparison, which is less efficient and not intended for structural matching. > > **1:M mapping example, U+00DF (?)** > > - String.toUpperCase(Locale.ROOT, "?") ? "SS" > - Case folding produces "ss", matching Unicode caseless comparison rules. > > > jshell> "\u00df".equalsIgnoreCase("ss") > $22 ==> false > > jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss") > $24 ==> true > > > ### Motivation & Direction > > Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching. > > - Unicode-compliant **full** case folding. > - Simpler, stable and more efficient case-less matching without workarounds. > - Brings Java's string comparison handling in line with other programming languages/libraries. > > This PR proposes to introduce the following comparison methods in `String` class > > - boolean equalsFoldCase(String anotherString) > - int compareToFoldCase(String anotherString) > - Comparator UNICODE_CASEFOLD_ORDER > > These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required. > > *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string. > However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then passed into APIs where case-folding semantics are not appropriate. > > ### The New API > > See CSR https://bugs.openjd... Xueming Shen has updated the pull request incrementally with one additional commit since the last revision: minor api doc updates ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27628/files - new: https://git.openjdk.org/jdk/pull/27628/files/1abb0228..9d9997dc Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27628&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27628&range=00-01 Stats: 18 lines in 1 file changed: 5 ins; 2 del; 11 mod Patch: https://git.openjdk.org/jdk/pull/27628.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27628/head:pull/27628 PR: https://git.openjdk.org/jdk/pull/27628 From rriggs at openjdk.org Wed Oct 8 13:24:48 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Wed, 8 Oct 2025 13:24:48 GMT Subject: RFR: 8365675: Add String Unicode Case-Folding Support [v2] In-Reply-To: References: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com> Message-ID: On Tue, 7 Oct 2025 22:18:58 GMT, Roger Riggs wrote: >> Xueming Shen has updated the pull request incrementally with one additional commit since the last revision: >> >> minor api doc updates > > src/java.base/share/classes/jdk/internal/lang/CaseFolding.java.template line 230: > >> 228: private static class CaseFoldingEntry { >> 229: final int cp; >> 230: final char[] folding; > > Consider storing the folding as a int or long directly to avoid the overhead of small char arrays. > Arrange to be able to compare the whole replacement with another codePoint, etc. I misunderstood the algorithm when comparing folded characters against non-folded sequences. I still think a fast path for single character replacements will lower memory costs and improve performance. The case of single-codepoint to single-codepoint dominates the case folding mappings. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27628#discussion_r2413846987 From liach at openjdk.org Wed Oct 8 14:14:26 2025 From: liach at openjdk.org (Chen Liang) Date: Wed, 8 Oct 2025 14:14:26 GMT Subject: RFR: 8365675: Add String Unicode Case-Folding Support [v2] In-Reply-To: References: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com> Message-ID: On Wed, 8 Oct 2025 00:33:20 GMT, Xueming Shen wrote: >> ### Summary >> >> Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions. >> >> Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as: >> >> **String.equalsIgnoreCase(String)** >> >> - Unicode-aware, locale-independent. >> - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point. >> - Limited: does not support 1:M mapping defined in Unicode case folding. >> >> **Character.toLowerCase(int) / Character.toUpperCase(int)** >> >> - Locale-independent, single code point only. >> - No support for 1:M mappings. >> >> **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)** >> >> - Based on Unicode SpecialCasing.txt, supports 1:M mappings. >> - Intended primarily for presentation/display, not structural case-insensitive matching. >> - Requires full string conversion before comparison, which is less efficient and not intended for structural matching. >> >> **1:M mapping example, U+00DF (?)** >> >> - String.toUpperCase(Locale.ROOT, "?") ? "SS" >> - Case folding produces "ss", matching Unicode caseless comparison rules. >> >> >> jshell> "\u00df".equalsIgnoreCase("ss") >> $22 ==> false >> >> jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss") >> $24 ==> true >> >> >> ### Motivation & Direction >> >> Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching. >> >> - Unicode-compliant **full** case folding. >> - Simpler, stable and more efficient case-less matching without workarounds. >> - Brings Java's string comparison handling in line with other programming languages/libraries. >> >> This PR proposes to introduce the following comparison methods in `String` class >> >> - boolean equalsFoldCase(String anotherString) >> - int compareToFoldCase(String anotherString) >> - Comparator UNICODE_CASEFOLD_ORDER >> >> These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required. >> >> *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string. >> However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then pass... > > Xueming Shen has updated the pull request incrementally with one additional commit since the last revision: > > minor api doc updates Given this patch obviously has so many performance optimization opportunities, I recommend handling those in subsequent RFEs so that we can review this purely from a specification point of view. make/modules/java.base/gensrc/GensrcCharacterData.gmk line 76: > 74: > 75: > 76: GENSRC_STRINGCASEFOLDING := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/jdk/internal/java/lang/CaseFolding.java Can we target the package `jdk.internal.lang` instead of `jdk.internal.java.lang`? I think the previous one is the convention set forth by stable values. ------------- PR Review: https://git.openjdk.org/jdk/pull/27628#pullrequestreview-3314954963 PR Review Comment: https://git.openjdk.org/jdk/pull/27628#discussion_r2413957017 From rriggs at openjdk.org Wed Oct 8 14:38:26 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Wed, 8 Oct 2025 14:38:26 GMT Subject: RFR: 8365675: Add String Unicode Case-Folding Support [v2] In-Reply-To: References: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com> Message-ID: On Wed, 8 Oct 2025 14:11:28 GMT, Chen Liang wrote: > Given this patch obviously has so many performance optimization opportunities, I recommend handling those in subsequent RFEs so that we can review this purely from a specification point of view. There is adequate time before RPD1 (Dec 4, 25) to improve performance, but the feature should not be included in JDK 26 unless the performance is comparable to the existing `compareToIgnoreCase` and `equalsIgnoreCase`. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27628#issuecomment-3381857251 From rriggs at openjdk.org Wed Oct 8 16:28:09 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Wed, 8 Oct 2025 16:28:09 GMT Subject: RFR: 8369184: SimpleTimeZone equals() Returns True for Unequal Instances with Different hashCode Values [v3] In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 20:43:20 GMT, Naoto Sato wrote: >> Fixing the equals/hashCode contract in the SimpleTimeZone class. The current implementation includes DST rule fields in hash code computation even for zones that do not observe DST, while equals() always considers them. Also correcting the example code in the class description, where it used 20-year-old obsolete "America/Los_Angeles" rule. > > Naoto Sato has updated the pull request incrementally with one additional commit since the last revision: > > Address review comments LGTM ------------- Marked as reviewed by rriggs (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27660#pullrequestreview-3315634206 From iris at openjdk.org Wed Oct 8 16:34:07 2025 From: iris at openjdk.org (Iris Clark) Date: Wed, 8 Oct 2025 16:34:07 GMT Subject: RFR: 8369184: SimpleTimeZone equals() Returns True for Unequal Instances with Different hashCode Values [v3] In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 20:43:20 GMT, Naoto Sato wrote: >> Fixing the equals/hashCode contract in the SimpleTimeZone class. The current implementation includes DST rule fields in hash code computation even for zones that do not observe DST, while equals() always considers them. Also correcting the example code in the class description, where it used 20-year-old obsolete "America/Los_Angeles" rule. > > Naoto Sato has updated the pull request incrementally with one additional commit since the last revision: > > Address review comments Marked as reviewed by iris (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27660#pullrequestreview-3315652499 From duke at openjdk.org Wed Oct 8 16:35:05 2025 From: duke at openjdk.org (Bernd) Date: Wed, 8 Oct 2025 16:35:05 GMT Subject: RFR: 8365675: Add String Unicode Case-Folding Support [v2] In-Reply-To: References: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com> Message-ID: <9c13AiS1RTrKhWGiVifePZ4CZa7Iws-AirXB-YMR4NQ=.cc24d342-334f-4be1-b886-7efd2c0a8898@github.com> On Wed, 8 Oct 2025 00:33:20 GMT, Xueming Shen wrote: >> ### Summary >> >> Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions. >> >> Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as: >> >> **String.equalsIgnoreCase(String)** >> >> - Unicode-aware, locale-independent. >> - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point. >> - Limited: does not support 1:M mapping defined in Unicode case folding. >> >> **Character.toLowerCase(int) / Character.toUpperCase(int)** >> >> - Locale-independent, single code point only. >> - No support for 1:M mappings. >> >> **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)** >> >> - Based on Unicode SpecialCasing.txt, supports 1:M mappings. >> - Intended primarily for presentation/display, not structural case-insensitive matching. >> - Requires full string conversion before comparison, which is less efficient and not intended for structural matching. >> >> **1:M mapping example, U+00DF (?)** >> >> - String.toUpperCase(Locale.ROOT, "?") ? "SS" >> - Case folding produces "ss", matching Unicode caseless comparison rules. >> >> >> jshell> "\u00df".equalsIgnoreCase("ss") >> $22 ==> false >> >> jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss") >> $24 ==> true >> >> >> ### Motivation & Direction >> >> Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching. >> >> - Unicode-compliant **full** case folding. >> - Simpler, stable and more efficient case-less matching without workarounds. >> - Brings Java's string comparison handling in line with other programming languages/libraries. >> >> This PR proposes to introduce the following comparison methods in `String` class >> >> - boolean equalsFoldCase(String anotherString) >> - int compareToFoldCase(String anotherString) >> - Comparator UNICODE_CASEFOLD_ORDER >> >> These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required. >> >> *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string. >> However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then pass... > > Xueming Shen has updated the pull request incrementally with one additional commit since the last revision: > > minor api doc updates Great progress thanks. Did you also consider a startsWith/containsCaseFold, I missed the case ignoring variants of those already. Or maybe provide an API to implement them on the cases folded intermediate buffers? If the API footprint gets too big on String as CaseFoldString.contains() helper maybe? ------------- PR Comment: https://git.openjdk.org/jdk/pull/27628#issuecomment-3382351349 From jlu at openjdk.org Wed Oct 8 17:27:15 2025 From: jlu at openjdk.org (Justin Lu) Date: Wed, 8 Oct 2025 17:27:15 GMT Subject: RFR: 8369184: SimpleTimeZone equals() Returns True for Unequal Instances with Different hashCode Values [v3] In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 20:43:20 GMT, Naoto Sato wrote: >> Fixing the equals/hashCode contract in the SimpleTimeZone class. The current implementation includes DST rule fields in hash code computation even for zones that do not observe DST, while equals() always considers them. Also correcting the example code in the class description, where it used 20-year-old obsolete "America/Los_Angeles" rule. > > Naoto Sato has updated the pull request incrementally with one additional commit since the last revision: > > Address review comments src/java.base/share/classes/java/util/SimpleTimeZone.java line 112: > 110: *

> 111: * The following are examples of parameters for constructing time zone objects. > 112: *



We can consider replacing `
` with `@snippet` so that the code example can be copied by readers. Although I understand if leaving it for another time as to not invalidate the existing approvals.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/27660#discussion_r2414548133

From prappo at openjdk.org  Wed Oct  8 17:36:50 2025
From: prappo at openjdk.org (Pavel Rappo)
Date: Wed, 8 Oct 2025 17:36:50 GMT
Subject:  RFR: 8369184: SimpleTimeZone equals() Returns True
 for Unequal Instances with Different hashCode Values [v3]
In-Reply-To: 
References: 
 
 
Message-ID: 

On Wed, 8 Oct 2025 17:24:19 GMT, Justin Lu  wrote:

>> Naoto Sato has updated the pull request incrementally with one additional commit since the last revision:
>> 
>>   Address review comments
>
> src/java.base/share/classes/java/util/SimpleTimeZone.java line 112:
> 
>> 110:  * 

>> 111: * The following are examples of parameters for constructing time zone objects. >> 112: *


> 
> We can consider replacing `
` with `@snippet` so that the code example can be copied by readers. Although I understand if leaving it for another time as to not invalidate the existing approvals.

I think, that's out of scope for this PR.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/27660#discussion_r2414569959

From naoto at openjdk.org  Wed Oct  8 17:42:44 2025
From: naoto at openjdk.org (Naoto Sato)
Date: Wed, 8 Oct 2025 17:42:44 GMT
Subject:  RFR: 8369050: DecimalFormat Rounding Errors for Ties
 Torwards 1 in LSD or 0
In-Reply-To: 
References: 
Message-ID: 

On Tue, 7 Oct 2025 23:19:28 GMT, Justin Lu  wrote:

> Please review this PR which corrects a rounding error for DecimalFormat on tie cases when the maximum fraction digits allowed is one less than the position of the first significant digit in the double rounded. For example, rounding a value such as 0.0005 to a maximum of 3 fractional digits. In order to get the correct `count` value, we must strip the trailing zeros prior to the check to ensure we have the correct value of `count` = 1 so that we can go down the _Rounding position is the last index_ case which properly checks if the String double was already rounded or is exact from its true decimal form.

LGTM

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

PR Review: https://git.openjdk.org/jdk/pull/27681#pullrequestreview-3315869483

From naoto at openjdk.org  Wed Oct  8 17:42:47 2025
From: naoto at openjdk.org (Naoto Sato)
Date: Wed, 8 Oct 2025 17:42:47 GMT
Subject:  RFR: 8369050: DecimalFormat Rounding Errors for Ties
 Torwards 1 in LSD or 0
In-Reply-To: 
References: 
 
Message-ID: 

On Tue, 7 Oct 2025 23:34:49 GMT, Justin Lu  wrote:

>> Please review this PR which corrects a rounding error for DecimalFormat on tie cases when the maximum fraction digits allowed is one less than the position of the first significant digit in the double rounded. For example, rounding a value such as 0.0005 to a maximum of 3 fractional digits. In order to get the correct `count` value, we must strip the trailing zeros prior to the check to ensure we have the correct value of `count` = 1 so that we can go down the _Rounding position is the last index_ case which properly checks if the String double was already rounded or is exact from its true decimal form.
>
> test/jdk/java/text/Format/DecimalFormat/RoundingToLSDTieTest.java line 1:
> 
>> 1: /*
> 
> I considered adding the tests in this file under _TieRoundingTest_, but did not do so to make review easier since JUnit could be used for the test in this PR. (_TieRoundingTest_ is old and does not use JUnit.) Will consider updating  _TieRoundingTest_ to use JUnit and merging the tests in this PR under it in a separate issue.

I think "LSD" is a bit cryptic. I'd spell-out or replace with other words if possible (and the PR/JBS titles too)

> test/jdk/java/text/Format/NumberFormat/NumberRegression.java line 1779:
> 
>> 1777:                 "0%", "0%", "1%", "1%", "1%",
>> 1778:                 "0", "2", "0.2", "0.6", "0.04",
>> 1779:                 "0.04", "0.001", "0.002",
> 
> This test is checking that `.0005` rounded to 3 digits is "0.000" under HALF_EVEN.
> 
> This is wrong. See,
> `new BigDecimal(0.0005) ==> 0.0005000000000000000104083408558608425664715468883514404296875`. 
> 
> Resolving the bug in this PR requires fixing this incorrect test case. From the JDK-4241880 issue, it seems this case may have been put in to "document the incorrect but actual behavior".

I guess this is the exact case this fix is trying to address, but the expected result wrongly assumes the behavior.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/27681#discussion_r2414578536
PR Review Comment: https://git.openjdk.org/jdk/pull/27681#discussion_r2414581725

From prappo at openjdk.org  Wed Oct  8 17:50:36 2025
From: prappo at openjdk.org (Pavel Rappo)
Date: Wed, 8 Oct 2025 17:50:36 GMT
Subject:  RFR: 8369184: SimpleTimeZone equals() Returns True
 for Unequal Instances with Different hashCode Values [v3]
In-Reply-To: 
References: 
 
Message-ID: 

On Tue, 7 Oct 2025 20:43:20 GMT, Naoto Sato  wrote:

>> Fixing the equals/hashCode contract in the SimpleTimeZone class. The current implementation includes DST rule fields in hash code computation even for zones that do not observe DST, while equals() always considers them. Also correcting the example code in the class description, where it used 20-year-old obsolete "America/Los_Angeles" rule.
>
> Naoto Sato has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Address review comments

test/jdk/java/util/TimeZone/SimpleTimeZoneEqualsHashCodeTest.java line 59:

> 57:         assertNotEquals(STZ_WITH_DST, stz);
> 58:         // from the contract point, hash codes may be the same
> 59:         assertNotEquals(STZ_WITH_DST.hashCode(), stz.hashCode());

Like you said, from `!a.equals(b)` it does not follow that `a.hashCode() != b.hashCode()`. Unless you want hash code to specifically have this additional property, I'd remove this assertion.

test/jdk/java/util/TimeZone/SimpleTimeZoneEqualsHashCodeTest.java line 63:

> 61: 
> 62:     @Test
> 63:     void withOutDSTTest() {

Nit, really:

Suggestion:

    void withoutDSTTest() {

test/jdk/java/util/TimeZone/SimpleTimeZoneEqualsHashCodeTest.java line 76:

> 74:         assertTrue(stz.useDaylightTime());
> 75:         assertNotEquals(STZ_WITHOUT_DST, stz);
> 76:         assertNotEquals(STZ_WITHOUT_DST.hashCode(), stz.hashCode());

Ditto on equals-hashCode contract.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/27660#discussion_r2414592801
PR Review Comment: https://git.openjdk.org/jdk/pull/27660#discussion_r2414583906
PR Review Comment: https://git.openjdk.org/jdk/pull/27660#discussion_r2414599801

From jlu at openjdk.org  Wed Oct  8 18:06:05 2025
From: jlu at openjdk.org (Justin Lu)
Date: Wed, 8 Oct 2025 18:06:05 GMT
Subject:  RFR: 8369050: DecimalFormat Rounding Errors for Ties
 Torwards 1 in LSD or 0
In-Reply-To: 
References: 
 
 
Message-ID: <-I2YDnaUqYuCyjvA0SZizCDga9zYdd4NVwvQjVjzn7I=.e82f011e-4801-436f-8b43-a8bf210b9efa@github.com>

On Wed, 8 Oct 2025 17:39:39 GMT, Naoto Sato  wrote:

>> test/jdk/java/text/Format/NumberFormat/NumberRegression.java line 1779:
>> 
>>> 1777:                 "0%", "0%", "1%", "1%", "1%",
>>> 1778:                 "0", "2", "0.2", "0.6", "0.04",
>>> 1779:                 "0.04", "0.001", "0.002",
>> 
>> This test is checking that `.0005` rounded to 3 digits is "0.000" under HALF_EVEN.
>> 
>> This is wrong. See,
>> `new BigDecimal(0.0005) ==> 0.0005000000000000000104083408558608425664715468883514404296875`. 
>> 
>> Resolving the bug in this PR requires fixing this incorrect test case. From the JDK-4241880 issue, it seems this case may have been put in to "document the incorrect but actual behavior".
>
> I guess this is the exact case this fix is trying to address, but the expected result wrongly assumes the behavior.

Right. This code used to return "0.000" because `count` would erroneously not be `1` for this specific case, hence going down the "there are additional digits" path. For HALF_EVEN, this returns true if there are additional non-zero digits past the last index. As there are none because the String double is given as ".0005", it rounded down.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/27681#discussion_r2414634438

From naoto at openjdk.org  Wed Oct  8 18:08:38 2025
From: naoto at openjdk.org (Naoto Sato)
Date: Wed, 8 Oct 2025 18:08:38 GMT
Subject:  RFR: 8369184: SimpleTimeZone equals() Returns True
 for Unequal Instances with Different hashCode Values [v4]
In-Reply-To: 
References: 
Message-ID: <9bOsoI7nGhYmcdwG8zRjBS74Oca_N5Cfh11iRaAP0oM=.68e1add0-b309-409b-ba95-b583ce99d44f@github.com>

> Fixing the equals/hashCode contract in the SimpleTimeZone class. The current implementation includes DST rule fields in hash code computation even for zones that do not observe DST, while equals() always considers them. Also correcting the example code in the class description, where it used 20-year-old obsolete "America/Los_Angeles" rule.

Naoto Sato has updated the pull request incrementally with one additional commit since the last revision:

  Apply suggestion from @pavelrappo
  
  Co-authored-by: Pavel Rappo <32523691+pavelrappo at users.noreply.github.com>

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

Changes:
  - all: https://git.openjdk.org/jdk/pull/27660/files
  - new: https://git.openjdk.org/jdk/pull/27660/files/aafdf18b..e764e2a6

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jdk&pr=27660&range=03
 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27660&range=02-03

  Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod
  Patch: https://git.openjdk.org/jdk/pull/27660.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/27660/head:pull/27660

PR: https://git.openjdk.org/jdk/pull/27660

From jlu at openjdk.org  Wed Oct  8 18:10:31 2025
From: jlu at openjdk.org (Justin Lu)
Date: Wed, 8 Oct 2025 18:10:31 GMT
Subject:  RFR: 8369050: DecimalFormat Rounding Errors for
 Fractional Ties Near Zero [v2]
In-Reply-To: 
References: 
Message-ID: <27RVFebqGufV83sFeY124966lHN1oi2x2Baa_p0P04Q=.319bfbc4-7fe0-4f3b-a66f-f4e52a8db928@github.com>

> Please review this PR which corrects a rounding error for DecimalFormat on tie cases when the maximum fraction digits allowed is one less than the position of the first significant digit in the double rounded. For example, rounding a value such as 0.0005 to a maximum of 3 fractional digits. In order to get the correct `count` value, we must strip the trailing zeros prior to the check to ensure we have the correct value of `count` = 1 so that we can go down the _Rounding position is the last index_ case which properly checks if the String double was already rounded or is exact from its true decimal form.

Justin Lu has updated the pull request incrementally with one additional commit since the last revision:

  Naoto's review -> test file rename

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

Changes:
  - all: https://git.openjdk.org/jdk/pull/27681/files
  - new: https://git.openjdk.org/jdk/pull/27681/files/6d22124e..1ebf7b0e

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jdk&pr=27681&range=01
 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27681&range=00-01

  Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod
  Patch: https://git.openjdk.org/jdk/pull/27681.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/27681/head:pull/27681

PR: https://git.openjdk.org/jdk/pull/27681

From naoto at openjdk.org  Wed Oct  8 18:15:39 2025
From: naoto at openjdk.org (Naoto Sato)
Date: Wed, 8 Oct 2025 18:15:39 GMT
Subject:  RFR: 8369184: SimpleTimeZone equals() Returns True
 for Unequal Instances with Different hashCode Values [v5]
In-Reply-To: 
References: 
Message-ID: 

> Fixing the equals/hashCode contract in the SimpleTimeZone class. The current implementation includes DST rule fields in hash code computation even for zones that do not observe DST, while equals() always considers them. Also correcting the example code in the class description, where it used 20-year-old obsolete "America/Los_Angeles" rule.

Naoto Sato has updated the pull request incrementally with one additional commit since the last revision:

  Reflects review comments

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

Changes:
  - all: https://git.openjdk.org/jdk/pull/27660/files
  - new: https://git.openjdk.org/jdk/pull/27660/files/e764e2a6..75ec7e71

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jdk&pr=27660&range=04
 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27660&range=03-04

  Stats: 6 lines in 1 file changed: 5 ins; 0 del; 1 mod
  Patch: https://git.openjdk.org/jdk/pull/27660.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/27660/head:pull/27660

PR: https://git.openjdk.org/jdk/pull/27660

From prappo at openjdk.org  Wed Oct  8 18:15:40 2025
From: prappo at openjdk.org (Pavel Rappo)
Date: Wed, 8 Oct 2025 18:15:40 GMT
Subject:  RFR: 8369184: SimpleTimeZone equals() Returns True
 for Unequal Instances with Different hashCode Values [v5]
In-Reply-To: 
References: 
 
Message-ID: 

On Wed, 8 Oct 2025 18:12:45 GMT, Naoto Sato  wrote:

>> Fixing the equals/hashCode contract in the SimpleTimeZone class. The current implementation includes DST rule fields in hash code computation even for zones that do not observe DST, while equals() always considers them. Also correcting the example code in the class description, where it used 20-year-old obsolete "America/Los_Angeles" rule.
>
> Naoto Sato has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Reflects review comments

Marked as reviewed by prappo (Reviewer).

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

PR Review: https://git.openjdk.org/jdk/pull/27660#pullrequestreview-3315973763

From naoto at openjdk.org  Wed Oct  8 18:15:42 2025
From: naoto at openjdk.org (Naoto Sato)
Date: Wed, 8 Oct 2025 18:15:42 GMT
Subject:  RFR: 8369184: SimpleTimeZone equals() Returns True
 for Unequal Instances with Different hashCode Values [v3]
In-Reply-To: 
References: 
 
 
Message-ID: 

On Wed, 8 Oct 2025 17:44:43 GMT, Pavel Rappo  wrote:

>> Naoto Sato has updated the pull request incrementally with one additional commit since the last revision:
>> 
>>   Address review comments
>
> test/jdk/java/util/TimeZone/SimpleTimeZoneEqualsHashCodeTest.java line 59:
> 
>> 57:         assertNotEquals(STZ_WITH_DST, stz);
>> 58:         // from the contract point, hash codes may be the same
>> 59:         assertNotEquals(STZ_WITH_DST.hashCode(), stz.hashCode());
> 
> Like you said, from `!a.equals(b)` it does not follow that `a.hashCode() != b.hashCode()`. Unless you want hash code to specifically have this additional property, I'd remove this assertion.

I wanted to test the implementation which takes DST related fields into consideration for hash code calculation. Added some comments for clarity

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

PR Review Comment: https://git.openjdk.org/jdk/pull/27660#discussion_r2414647340

From liach at openjdk.org  Wed Oct  8 18:23:26 2025
From: liach at openjdk.org (Chen Liang)
Date: Wed, 8 Oct 2025 18:23:26 GMT
Subject:  RFR: 8365675: Add String Unicode Case-Folding
 Support [v2]
In-Reply-To: <9c13AiS1RTrKhWGiVifePZ4CZa7Iws-AirXB-YMR4NQ=.cc24d342-334f-4be1-b886-7efd2c0a8898@github.com>
References: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com>
 
 <9c13AiS1RTrKhWGiVifePZ4CZa7Iws-AirXB-YMR4NQ=.cc24d342-334f-4be1-b886-7efd2c0a8898@github.com>
Message-ID: 

On Wed, 8 Oct 2025 16:31:53 GMT, Bernd  wrote:

> Did you also consider a startsWith/containsCaseFold, I missed the case ignoring variants of those already.

I think for this purpose, we should rather introduce an API to case fold a string - we can use these operations on the case-fold-normalized strings.

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

PR Comment: https://git.openjdk.org/jdk/pull/27628#issuecomment-3382715644

From naoto at openjdk.org  Wed Oct  8 18:26:25 2025
From: naoto at openjdk.org (Naoto Sato)
Date: Wed, 8 Oct 2025 18:26:25 GMT
Subject:  RFR: 8369050: DecimalFormat Rounding Errors for
 Fractional Ties Near Zero [v2]
In-Reply-To: <27RVFebqGufV83sFeY124966lHN1oi2x2Baa_p0P04Q=.319bfbc4-7fe0-4f3b-a66f-f4e52a8db928@github.com>
References: 
 <27RVFebqGufV83sFeY124966lHN1oi2x2Baa_p0P04Q=.319bfbc4-7fe0-4f3b-a66f-f4e52a8db928@github.com>
Message-ID: 

On Wed, 8 Oct 2025 18:10:31 GMT, Justin Lu  wrote:

>> Please review this PR which corrects a rounding error for DecimalFormat on tie cases when the maximum fraction digits allowed is one less than the position of the first significant digit in the double rounded. For example, rounding a value such as 0.0005 to a maximum of 3 fractional digits. In order to get the correct `count` value, we must strip the trailing zeros prior to the check to ensure we have the correct value of `count` = 1 so that we can go down the _Rounding position is the last index_ case which properly checks if the String double was already rounded or is exact from its true decimal form.
>
> Justin Lu has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Naoto's review -> test file rename

Marked as reviewed by naoto (Reviewer).

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

PR Review: https://git.openjdk.org/jdk/pull/27681#pullrequestreview-3316021946

From rriggs at openjdk.org  Wed Oct  8 18:40:58 2025
From: rriggs at openjdk.org (Roger Riggs)
Date: Wed, 8 Oct 2025 18:40:58 GMT
Subject:  RFR: 8365675: Add String Unicode Case-Folding
 Support [v2]
In-Reply-To: 
References: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com>
 
Message-ID: 

On Wed, 8 Oct 2025 00:33:20 GMT, Xueming Shen  wrote:

>> ### Summary
>> 
>> Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions.
>> 
>> Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as:
>> 
>> **String.equalsIgnoreCase(String)**
>> 
>> - Unicode-aware, locale-independent.
>> - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point.
>> - Limited: does not support 1:M mapping defined in Unicode case folding.
>> 
>> **Character.toLowerCase(int) / Character.toUpperCase(int)**
>> 
>> - Locale-independent, single code point only.
>> - No support for 1:M mappings.
>> 
>> **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)**
>> 
>> - Based on Unicode SpecialCasing.txt, supports 1:M mappings.
>> - Intended primarily for presentation/display, not structural case-insensitive matching.
>> - Requires full string conversion before comparison, which is less efficient and not intended for structural matching.
>> 
>> **1:M mapping example, U+00DF (?)**
>> 
>> - String.toUpperCase(Locale.ROOT, "?") ? "SS"
>> - Case folding produces "ss", matching Unicode caseless comparison rules.
>> 
>> 
>> jshell> "\u00df".equalsIgnoreCase("ss")
>> $22 ==> false
>> 
>> jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss")
>> $24 ==> true
>> 
>> 
>> ### Motivation & Direction
>> 
>> Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching.
>> 
>> - Unicode-compliant **full** case folding.
>> - Simpler, stable and more efficient case-less matching without workarounds.
>> - Brings Java's string comparison handling in line with other programming languages/libraries.
>> 
>> This PR proposes to introduce the following comparison methods in `String` class
>> 
>> - boolean equalsFoldCase(String anotherString)
>> - int compareToFoldCase(String anotherString)
>> - Comparator UNICODE_CASEFOLD_ORDER
>> 
>> These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required.
>> 
>> *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string.
>> However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then pass...
>
> Xueming Shen has updated the pull request incrementally with one additional commit since the last revision:
> 
>   minor api doc updates

The new APIs mentioned would be more effective, leveraging the underlying implementation without needing to create new Strings.  Earlier discussions of the support for folding, raised a concern about tempting developers to a more ambiguous situation in which folded and unfolded strings exist and can be confused.

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

PR Comment: https://git.openjdk.org/jdk/pull/27628#issuecomment-3382766309

From liach at openjdk.org  Wed Oct  8 18:58:30 2025
From: liach at openjdk.org (Chen Liang)
Date: Wed, 8 Oct 2025 18:58:30 GMT
Subject:  RFR: 8365675: Add String Unicode Case-Folding
 Support [v2]
In-Reply-To: 
References: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com>
 
Message-ID: 

On Wed, 8 Oct 2025 00:33:20 GMT, Xueming Shen  wrote:

>> ### Summary
>> 
>> Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions.
>> 
>> Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as:
>> 
>> **String.equalsIgnoreCase(String)**
>> 
>> - Unicode-aware, locale-independent.
>> - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point.
>> - Limited: does not support 1:M mapping defined in Unicode case folding.
>> 
>> **Character.toLowerCase(int) / Character.toUpperCase(int)**
>> 
>> - Locale-independent, single code point only.
>> - No support for 1:M mappings.
>> 
>> **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)**
>> 
>> - Based on Unicode SpecialCasing.txt, supports 1:M mappings.
>> - Intended primarily for presentation/display, not structural case-insensitive matching.
>> - Requires full string conversion before comparison, which is less efficient and not intended for structural matching.
>> 
>> **1:M mapping example, U+00DF (?)**
>> 
>> - String.toUpperCase(Locale.ROOT, "?") ? "SS"
>> - Case folding produces "ss", matching Unicode caseless comparison rules.
>> 
>> 
>> jshell> "\u00df".equalsIgnoreCase("ss")
>> $22 ==> false
>> 
>> jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss")
>> $24 ==> true
>> 
>> 
>> ### Motivation & Direction
>> 
>> Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching.
>> 
>> - Unicode-compliant **full** case folding.
>> - Simpler, stable and more efficient case-less matching without workarounds.
>> - Brings Java's string comparison handling in line with other programming languages/libraries.
>> 
>> This PR proposes to introduce the following comparison methods in `String` class
>> 
>> - boolean equalsFoldCase(String anotherString)
>> - int compareToFoldCase(String anotherString)
>> - Comparator UNICODE_CASEFOLD_ORDER
>> 
>> These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required.
>> 
>> *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string.
>> However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then pass...
>
> Xueming Shen has updated the pull request incrementally with one additional commit since the last revision:
> 
>   minor api doc updates

I don't think it's a good idea to have an explosion of case-folding variants of string operations if we are adding a case-folding overload for every operation. In that case, the confusion of case folding applicability would be less of a problem compared to the API bloat.

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

PR Comment: https://git.openjdk.org/jdk/pull/27628#issuecomment-3382818647

From rriggs at openjdk.org  Wed Oct  8 20:16:25 2025
From: rriggs at openjdk.org (Roger Riggs)
Date: Wed, 8 Oct 2025 20:16:25 GMT
Subject:  RFR: 8366829: Add java.time.Duration constants MIN
 and MAX [v3]
In-Reply-To: 
References: 
 
Message-ID: 

On Fri, 3 Oct 2025 09:50:23 GMT, Pavel Rappo  wrote:

>> We have [recently discussed][] a possibility of adding the `Duration.MIN` and `Duration.MAX` constants. Can we now start implementation? If and when we are in agreement on this PR, I will file a CSR.
>> 
>> I drafted a minimal specification and added some tests. I tried to phrase the spec for `Duration.MIN` in a way that makes it clear that `Duration.MIN` is the most negative value and not the least positive.
>> 
>> [recently discussed]: https://mail.openjdk.org/pipermail/core-libs-dev/2025-September/151098.html
>
> Pavel Rappo has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Respond to feedback
>   
>   Apply Stephen's suggestion on wording, although modified.

As proposed. Duration.MAX() is not the negated value of Duration.MIN.
Is there any value for them to have that mathematical property?
Duration.MIN can not be negated, it throws "Exceeds capacity of Duration".

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

PR Comment: https://git.openjdk.org/jdk/pull/27534#issuecomment-3383068470

From duke at openjdk.org  Thu Oct  9 16:11:02 2025
From: duke at openjdk.org (Bernd)
Date: Thu, 9 Oct 2025 16:11:02 GMT
Subject:  RFR: 8365675: Add String Unicode Case-Folding
 Support [v2]
In-Reply-To: 
References: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com>
 
Message-ID: <7FNQkL6cersUolPLQ1NViK0811Mx3AkaNzid3tQktbI=.2eaa33d4-8051-486a-b305-a5d4000948de@github.com>

On Wed, 8 Oct 2025 00:33:20 GMT, Xueming Shen  wrote:

>> ### Summary
>> 
>> Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions.
>> 
>> Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as:
>> 
>> **String.equalsIgnoreCase(String)**
>> 
>> - Unicode-aware, locale-independent.
>> - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point.
>> - Limited: does not support 1:M mapping defined in Unicode case folding.
>> 
>> **Character.toLowerCase(int) / Character.toUpperCase(int)**
>> 
>> - Locale-independent, single code point only.
>> - No support for 1:M mappings.
>> 
>> **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)**
>> 
>> - Based on Unicode SpecialCasing.txt, supports 1:M mappings.
>> - Intended primarily for presentation/display, not structural case-insensitive matching.
>> - Requires full string conversion before comparison, which is less efficient and not intended for structural matching.
>> 
>> **1:M mapping example, U+00DF (?)**
>> 
>> - String.toUpperCase(Locale.ROOT, "?") ? "SS"
>> - Case folding produces "ss", matching Unicode caseless comparison rules.
>> 
>> 
>> jshell> "\u00df".equalsIgnoreCase("ss")
>> $22 ==> false
>> 
>> jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss")
>> $24 ==> true
>> 
>> 
>> ### Motivation & Direction
>> 
>> Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching.
>> 
>> - Unicode-compliant **full** case folding.
>> - Simpler, stable and more efficient case-less matching without workarounds.
>> - Brings Java's string comparison handling in line with other programming languages/libraries.
>> 
>> This PR proposes to introduce the following comparison methods in `String` class
>> 
>> - boolean equalsFoldCase(String anotherString)
>> - int compareToFoldCase(String anotherString)
>> - Comparator UNICODE_CASEFOLD_ORDER
>> 
>> These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required.
>> 
>> *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string.
>> However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then pass...
>
> Xueming Shen has updated the pull request incrementally with one additional commit since the last revision:
> 
>   minor api doc updates

src/java.base/share/classes/jdk/internal/lang/CaseFolding.java.template line 36:

> 34: 
> 35: /**
> 36:  * Utility class for {@code String.toCaseFold()} that handles Unicode case folding

Maybe make it clear this is a planned api (or not refer to it?)

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

PR Review Comment: https://git.openjdk.org/jdk/pull/27628#discussion_r2417269101

From naoto at openjdk.org  Thu Oct  9 16:23:49 2025
From: naoto at openjdk.org (Naoto Sato)
Date: Thu, 9 Oct 2025 16:23:49 GMT
Subject:  RFR: 8369184: SimpleTimeZone equals() Returns True
 for Unequal Instances with Different hashCode Values [v5]
In-Reply-To: 
References: 
 
Message-ID: 

On Wed, 8 Oct 2025 18:15:39 GMT, Naoto Sato  wrote:

>> Fixing the equals/hashCode contract in the SimpleTimeZone class. The current implementation includes DST rule fields in hash code computation even for zones that do not observe DST, while equals() always considers them. Also correcting the example code in the class description, where it used 20-year-old obsolete "America/Los_Angeles" rule.
>
> Naoto Sato has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Reflects review comments

Thanks for the reviews!

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

PR Comment: https://git.openjdk.org/jdk/pull/27660#issuecomment-3386564567

From naoto at openjdk.org  Thu Oct  9 16:23:51 2025
From: naoto at openjdk.org (Naoto Sato)
Date: Thu, 9 Oct 2025 16:23:51 GMT
Subject:  Integrated: 8369184: SimpleTimeZone equals() Returns
 True for Unequal Instances with Different hashCode Values
In-Reply-To: 
References: 
Message-ID: 

On Mon, 6 Oct 2025 21:36:44 GMT, Naoto Sato  wrote:

> Fixing the equals/hashCode contract in the SimpleTimeZone class. The current implementation includes DST rule fields in hash code computation even for zones that do not observe DST, while equals() always considers them. Also correcting the example code in the class description, where it used 20-year-old obsolete "America/Los_Angeles" rule.

This pull request has now been integrated.

Changeset: 37b725d9
Author:    Naoto Sato 
URL:       https://git.openjdk.org/jdk/commit/37b725d9c12834358a562e6c03fb7f566d639ca5
Stats:     102 lines in 2 files changed: 94 ins; 0 del; 8 mod

8369184: SimpleTimeZone equals() Returns True for Unequal Instances with Different hashCode Values

Reviewed-by: prappo, jlu, rriggs, iris

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

PR: https://git.openjdk.org/jdk/pull/27660

From jlu at openjdk.org  Thu Oct  9 18:19:13 2025
From: jlu at openjdk.org (Justin Lu)
Date: Thu, 9 Oct 2025 18:19:13 GMT
Subject:  RFR: 8369452: Locale.Builder.setLanguageTag(String) does
 not clear on empty or null String
Message-ID: 

Please review this PR which corrects the behavior of `Locale.Builder.setLanguageTag(String)` on the null and empty String case.

> Null and the empty string cause the builder to be reset

Currently, NPE is thrown for a null tag, and ILE is thrown for an empty String. They are both corrected to not throw, and instead reset the state of the `Locale.Builder`.

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

Commit messages:
 - The fix and reg test

Changes: https://git.openjdk.org/jdk/pull/27734/files
  Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27734&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8369452
  Stats: 25 lines in 2 files changed: 20 ins; 0 del; 5 mod
  Patch: https://git.openjdk.org/jdk/pull/27734.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/27734/head:pull/27734

PR: https://git.openjdk.org/jdk/pull/27734

From prappo at openjdk.org  Thu Oct  9 21:36:01 2025
From: prappo at openjdk.org (Pavel Rappo)
Date: Thu, 9 Oct 2025 21:36:01 GMT
Subject:  RFR: 8366829: Add java.time.Duration constants MIN
 and MAX [v3]
In-Reply-To: 
References: 
 
 
Message-ID: 

On Wed, 8 Oct 2025 20:13:50 GMT, Roger Riggs  wrote:

> As proposed. Duration.MAX() is not the negated value of Duration.MIN. Is there any value for them to have that mathematical property? Duration.MIN can not be negated, it throws "Exceeds capacity of Duration".

To future readers: initially this question was asked in [another PR][], and then I forwarded it to this [mailing list discussion][].

[another PR]: https://github.com/openjdk/jdk/pull/27549#discussion_r2414774950
[mailing list discussion]: https://mail.openjdk.org/pipermail/core-libs-dev/2025-October/153062.html

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

PR Comment: https://git.openjdk.org/jdk/pull/27534#issuecomment-3387557653

From duke at openjdk.org  Thu Oct  9 23:17:14 2025
From: duke at openjdk.org (duke)
Date: Thu, 9 Oct 2025 23:17:14 GMT
Subject:  Withdrawn: 8359068: Remove the unused Cstyle code in
 GenerateCharacter
In-Reply-To: 
References: 
Message-ID: 

On Wed, 28 May 2025 03:44:22 GMT, Shaojin Wen  wrote:

> According to the suggestions of @cl4es and @naotoj, Cstyle is no longer used in GenerateCharacter, so remove the Cstyle related code.

This pull request has been closed without being integrated.

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

PR: https://git.openjdk.org/jdk/pull/25480

From naoto at openjdk.org  Thu Oct  9 23:30:01 2025
From: naoto at openjdk.org (Naoto Sato)
Date: Thu, 9 Oct 2025 23:30:01 GMT
Subject:  RFR: 8369452: Locale.Builder.setLanguageTag(String)
 does not clear on empty or null String
In-Reply-To: 
References: 
Message-ID: 

On Thu, 9 Oct 2025 18:12:58 GMT, Justin Lu  wrote:

> Please review this PR which corrects the behavior of `Locale.Builder.setLanguageTag(String)` on the null and empty String case.
> 
> This method is specified as follows,
> 
>> Null and the empty string cause the builder to be reset
> 
> Currently, NPE is thrown for a null tag, and ILE is thrown for an empty String. They are both corrected to not throw, and instead reset the state of the `Locale.Builder`.

LGTM

test/jdk/java/util/Locale/LocaleEnhanceTest.java line 779:

> 777:         bldr.setLanguageTag("en-US");
> 778:         assertDoesNotThrow(() -> bldr.setLanguageTag(tag));
> 779:         assertEquals(tag + " did not clear the builder", empty.build(), bldr.build());

Should not happen, but if empty string caused an assertion failure, the error message starts with " did not clear..."

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

Marked as reviewed by naoto (Reviewer).

PR Review: https://git.openjdk.org/jdk/pull/27734#pullrequestreview-3320916918
PR Review Comment: https://git.openjdk.org/jdk/pull/27734#discussion_r2418168857

From jlu at openjdk.org  Thu Oct  9 23:42:39 2025
From: jlu at openjdk.org (Justin Lu)
Date: Thu, 9 Oct 2025 23:42:39 GMT
Subject:  RFR: 8369452: Locale.Builder.setLanguageTag(String)
 does not clear on empty or null String [v2]
In-Reply-To: 
References: 
Message-ID: 

> Please review this PR which corrects the behavior of `Locale.Builder.setLanguageTag(String)` on the null and empty String case.
> 
> This method is specified as follows,
> 
>> Null and the empty string cause the builder to be reset
> 
> Currently, NPE is thrown for a null tag, and ILE is thrown for an empty String. They are both corrected to not throw, and instead reset the state of the `Locale.Builder`.

Justin Lu has updated the pull request incrementally with one additional commit since the last revision:

  Naoto's comment - improve err msg

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

Changes:
  - all: https://git.openjdk.org/jdk/pull/27734/files
  - new: https://git.openjdk.org/jdk/pull/27734/files/68bb29a1..fa385c8a

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jdk&pr=27734&range=01
 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27734&range=00-01

  Stats: 3 lines in 1 file changed: 2 ins; 0 del; 1 mod
  Patch: https://git.openjdk.org/jdk/pull/27734.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/27734/head:pull/27734

PR: https://git.openjdk.org/jdk/pull/27734

From jlu at openjdk.org  Thu Oct  9 23:42:40 2025
From: jlu at openjdk.org (Justin Lu)
Date: Thu, 9 Oct 2025 23:42:40 GMT
Subject:  RFR: 8369452: Locale.Builder.setLanguageTag(String)
 does not clear on empty or null String [v2]
In-Reply-To: 
References: 
 
Message-ID: 

On Thu, 9 Oct 2025 23:27:06 GMT, Naoto Sato  wrote:

>> Justin Lu has updated the pull request incrementally with one additional commit since the last revision:
>> 
>>   Naoto's comment - improve err msg
>
> test/jdk/java/util/Locale/LocaleEnhanceTest.java line 779:
> 
>> 777:         bldr.setLanguageTag("en-US");
>> 778:         assertDoesNotThrow(() -> bldr.setLanguageTag(tag));
>> 779:         assertEquals(tag + " did not clear the builder", empty.build(), bldr.build());
> 
> Should not happen, but if empty string caused an assertion failure, the error message starts with " did not clear..."

Good point, updated.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/27734#discussion_r2418189274

From naoto at openjdk.org  Fri Oct 10 16:13:05 2025
From: naoto at openjdk.org (Naoto Sato)
Date: Fri, 10 Oct 2025 16:13:05 GMT
Subject:  RFR: 8369452: Locale.Builder.setLanguageTag(String)
 does not clear on empty or null String [v2]
In-Reply-To: 
References: 
 
Message-ID: 

On Thu, 9 Oct 2025 23:42:39 GMT, Justin Lu  wrote:

>> Please review this PR which corrects the behavior of `Locale.Builder.setLanguageTag(String)` on the null and empty String case.
>> 
>> This method is specified as follows,
>> 
>>> Null and the empty string cause the builder to be reset
>> 
>> Currently, NPE is thrown for a null tag, and ILE is thrown for an empty String. They are both corrected to not throw, and instead reset the state of the `Locale.Builder`.
>
> Justin Lu has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Naoto's comment - improve err msg

Marked as reviewed by naoto (Reviewer).

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

PR Review: https://git.openjdk.org/jdk/pull/27734#pullrequestreview-3324546666

From jlu at openjdk.org  Fri Oct 10 16:31:00 2025
From: jlu at openjdk.org (Justin Lu)
Date: Fri, 10 Oct 2025 16:31:00 GMT
Subject:  Integrated: 8369050: DecimalFormat Rounding Errors for
 Fractional Ties Near Zero
In-Reply-To: 
References: 
Message-ID: 

On Tue, 7 Oct 2025 23:19:28 GMT, Justin Lu  wrote:

> Please review this PR which corrects a rounding error for DecimalFormat on tie cases when the maximum fraction digits allowed is one less than the position of the first significant digit in the double rounded. For example, rounding a value such as 0.0005 to a maximum of 3 fractional digits. In order to get the correct `count` value, we must strip the trailing zeros prior to the check to ensure we have the correct value of `count` = 1 so that we can go down the _Rounding position is the last index_ case which properly checks if the String double was already rounded or is exact from its true decimal form.

This pull request has now been integrated.

Changeset: 376d77e8
Author:    Justin Lu 
URL:       https://git.openjdk.org/jdk/commit/376d77e8a71478f456af5baaf47f446eebd79e36
Stats:     95 lines in 3 files changed: 88 ins; 5 del; 2 mod

8369050: DecimalFormat Rounding Errors for Fractional Ties Near Zero

Reviewed-by: naoto

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

PR: https://git.openjdk.org/jdk/pull/27681

From duke at openjdk.org  Fri Oct 10 19:52:04 2025
From: duke at openjdk.org (=?UTF-8?B?SmVhbi1Ob8OrbA==?= Rouvignac)
Date: Fri, 10 Oct 2025 19:52:04 GMT
Subject:  RFR: 8365675: Add String Unicode Case-Folding
 Support [v2]
In-Reply-To: 
References: <3tMaotmLtDYKP4cADaC8DEISDKEJEaWHXr2dYDtZXY8=.22820982-951a-4e91-96a0-d21397c8494d@github.com>
 
Message-ID: 

On Wed, 8 Oct 2025 00:33:20 GMT, Xueming Shen  wrote:

>> ### Summary
>> 
>> Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions.
>> 
>> Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as:
>> 
>> **String.equalsIgnoreCase(String)**
>> 
>> - Unicode-aware, locale-independent.
>> - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point.
>> - Limited: does not support 1:M mapping defined in Unicode case folding.
>> 
>> **Character.toLowerCase(int) / Character.toUpperCase(int)**
>> 
>> - Locale-independent, single code point only.
>> - No support for 1:M mappings.
>> 
>> **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)**
>> 
>> - Based on Unicode SpecialCasing.txt, supports 1:M mappings.
>> - Intended primarily for presentation/display, not structural case-insensitive matching.
>> - Requires full string conversion before comparison, which is less efficient and not intended for structural matching.
>> 
>> **1:M mapping example, U+00DF (?)**
>> 
>> - String.toUpperCase(Locale.ROOT, "?") ? "SS"
>> - Case folding produces "ss", matching Unicode caseless comparison rules.
>> 
>> 
>> jshell> "\u00df".equalsIgnoreCase("ss")
>> $22 ==> false
>> 
>> jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss")
>> $24 ==> true
>> 
>> 
>> ### Motivation & Direction
>> 
>> Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching.
>> 
>> - Unicode-compliant **full** case folding.
>> - Simpler, stable and more efficient case-less matching without workarounds.
>> - Brings Java's string comparison handling in line with other programming languages/libraries.
>> 
>> This PR proposes to introduce the following comparison methods in `String` class
>> 
>> - boolean equalsFoldCase(String anotherString)
>> - int compareToFoldCase(String anotherString)
>> - Comparator UNICODE_CASEFOLD_ORDER
>> 
>> These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required.
>> 
>> *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string.
>> However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then pass...
>
> Xueming Shen has updated the pull request incrementally with one additional commit since the last revision:
> 
>   minor api doc updates

test/micro/org/openjdk/bench/java/lang/StringCompareToIgnoreCase.java line 89:

> 87: 
> 88:     @Benchmark
> 89:     public int lowerrCF() {

Suggestion:

    public int lowerCF() {

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

PR Review Comment: https://git.openjdk.org/jdk/pull/27628#discussion_r2421934368

From pminborg at openjdk.org  Mon Oct 13 11:51:02 2025
From: pminborg at openjdk.org (Per Minborg)
Date: Mon, 13 Oct 2025 11:51:02 GMT
Subject:  RFR: 8366178: Implement JEP 526: Lazy Constants (Second
 Preview)
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.

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

Commit messages:
 - Add optimization where the computing function is returned directly
 - Add benchmark of Optionals
 - Merge branch 'master' into lazy-constants
 - Update src/java.base/share/classes/java/lang/LazyConstant.java
 - Update src/java.base/share/classes/java/util/LazyCollections.java
 - Fix failing test
 - Clean up
 - Merge branch 'master' into lazy-constants
 - Update JEP number
 - Fix doc issues
 - ... and 76 more: https://git.openjdk.org/jdk/compare/1605e839...3e287031

Changes: https://git.openjdk.org/jdk/pull/27605/files
  Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8366178
  Stats: 8721 lines in 60 files changed: 4112 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 duke at openjdk.org  Mon Oct 13 11:51:02 2025
From: duke at openjdk.org (ExE Boss)
Date: Mon, 13 Oct 2025 11:51:02 GMT
Subject:  RFR: 8366178: Implement JEP 526: Lazy Constants
 (Second Preview)
In-Reply-To: 
References: 
Message-ID: <8VsjXECvVSYRtKpK4PId8s_8RM0T00n4BzmfO6RTinM=.e1bb59c4-8a85-4d3c-8980-249cd529b50b@github.com>

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.

I?m?gonna?miss **Stable?Values**, as?it?has some?use?cases which?aren?t?served by?**Lazy?Constants**, and?on?which I?depend?on in?some of?my?code, so?I?m stuck?with using?regular non?`final`?fields.

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

Also, in the [JEP?526]?table under ?[Flexible?initialization with?lazy?constants]?:
> |                 	| Update count	| Update location	| Constant folding?	| Concurrent updates?
> | --------------  	| ------------	| ---------------	| -----------------	| -------------------
> | `final` field   	| 1         	| Constructor or static initializer	| Yes 	| No
> | `LazyConstant`  	| [0, 1]    	| Anywhere	| Yes, after initialization	| Yes, by winner
> | Non-`final` field	| [0, ?)    	| Anywhere	| No 	| Yes

The??Update?location? of?`LazyConstant` shouldn?t?be??Anywhere?, as?that?was only?accurate for?`StableValue`, but?not for?`LazyConstant`, which?is?updated by?calling the?passed `Supplier`.

Similarly, concurrent?updates are?prevented for?`LazyConstant`s by?using `synchronized?(this)`.

[JEP?526]: https://openjdk.org/jeps/526
[Flexible?initialization with?lazy?constants]: https://openjdk.org/jeps/526#Flexible-initialization-with-lazy-constants

Getting?access to?the?underlying `StableValue`?API with?**Lazy?Constants** is?way?too?hacky and?convoluted (but?doable):
StableVar.java /* * Any copyright is dedicated to the Public Domain. * https://creativecommons.org/publicdomain/zero/1.0/ */ import java.util.NoSuchElementException; import java.util.function.Supplier; import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; import static java.lang.System.identityHashCode; import static java.util.Objects.requireNonNull; /// Horrible awful hack to get access to raw stable values in JDK 26+. @NullMarked public sealed interface StableVar permits StableHacks.StableVarImpl { boolean trySet(final T contents) throws NullPointerException, IllegalStateException; @Nullable T orNull(); T orElse(final T other) throws NullPointerException; T orElseThrow() throws NoSuchElementException; boolean isSet(); T orElseSet(final Supplier supplier) throws NullPointerException, IllegalStateException; void setOrThrow(final T contents) throws NullPointerException, IllegalStateException; static StableVar of() { return StableHacks.newInstance(); } } /// Encapsulates the actual implementation of `StableValue` on `LazyConstant` /// /// @author ExE Boss @NullMarked /*package*/ final @Namespace class StableHacks { private StableHacks() throws InstantiationException { throw new InstantiationException(StableHacks.class.getName()); } private static final String UNSET_SUFFIX = ".unset"; private static final Object UNSET = new Object() { @Override public int hashCode() { return 0; } @Override public String toString() { return "unset"; } }; private static final ScopedValue SCOPE = ScopedValue.newInstance(); private static final Supplier SCOPE_GETTER = SCOPE::get; /*package*/ static final StableVarImpl newInstance() { return new StableValue<>(); } /*package*/ sealed interface StableVarImpl extends StableVar { } private record StableValue( // Implemented as a record so that the JVM treats this as a trusted final field // even when `-XX:+TrustFinalNonStaticFields` is not set LazyConstant contents ) implements StableVarImpl { @SuppressWarnings("unchecked") private StableValue() { this(LazyConstant.of((Supplier) SCOPE_GETTER)); } private StableValue { if (contents.isInitialized()) throw new InternalError(); } @SuppressWarnings("unchecked") private final ScopedValue scope() { return (ScopedValue) SCOPE; } private final void preventReentry() throws IllegalStateException { if (Thread.holdsLock(this)) { throw new IllegalStateException("Recursive initialization of a stable value is illegal"); } } @Override public boolean trySet(final T contents) throws NullPointerException, IllegalStateException { requireNonNull(contents); if (this.contents.isInitialized()) return false; preventReentry(); synchronized (this) { return this.setImpl(contents); } } @Override @SuppressWarnings("unchecked") public final @Nullable T orNull() { return unwrapUnset(((LazyConstant) this.contents).orElse(UNSET)); } @Override public T orElse(T other) throws NullPointerException { return this.contents.orElse(other); } @Override public T orElseThrow() throws NoSuchElementException { { final T contents; if ((contents = this.orNull()) != null) { return contents; } } throw new NoSuchElementException(); } @Override public boolean isSet() { return this.contents.isInitialized(); } @Override public T orElseSet(final Supplier supplier) throws NullPointerException, IllegalStateException { requireNonNull(supplier); { final T contents; if ((contents = this.orNull()) != null) { return contents; } } return orElseSetSlowPath(supplier); } @Override public void setOrThrow(final T contents) throws NullPointerException, IllegalStateException { if (!trySet(contents)) { throw new IllegalStateException(); } } private final T orElseSetSlowPath( final Supplier supplier ) throws NullPointerException, IllegalStateException { preventReentry(); synchronized (this) { { final T contents; if ((contents = this.orNull()) != null) { return contents; } } final T newValue; this.setImpl(newValue = requireNonNull(supplier.get())); return newValue; } } private final boolean setImpl(final T contents) { assert Thread.holdsLock(this); if (this.contents.isInitialized()) { return false; } ScopedValue.where(this.scope(), contents).run(this.contents::get); return true; } @Override public final boolean equals(final Object obj) { return this == obj; } @Override public final int hashCode() { return identityHashCode(this); } @Override public String toString() { final Object contents; return renderValue( "StableValue", (contents = this.orNull()) != this ? contents : "(this StableValue)" ); } } @SuppressWarnings("unchecked") private static final @Nullable T unwrapUnset(final @Nullable Object obj) { return (obj == UNSET) ? null : (T) obj; } private static final String renderValue( final String type, final @Nullable Object value ) throws NullPointerException { return (value == null) ? type.concat(UNSET_SUFFIX) : (type + '[' + value + ']'); } }
------------- PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3367784825 PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3368298279 From liach at openjdk.org Mon Oct 13 11:51:04 2025 From: liach at openjdk.org (Chen Liang) Date: Mon, 13 Oct 2025 11:51:04 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: <8VsjXECvVSYRtKpK4PId8s_8RM0T00n4BzmfO6RTinM=.e1bb59c4-8a85-4d3c-8980-249cd529b50b@github.com> References: <8VsjXECvVSYRtKpK4PId8s_8RM0T00n4BzmfO6RTinM=.e1bb59c4-8a85-4d3c-8980-249cd529b50b@github.com> Message-ID: On Sat, 4 Oct 2025 14:29:08 GMT, ExE Boss 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. > > Getting?access to?the?underlying `StableValue`?API with?**Lazy?Constants** is?way?too?hacky and?convoluted (but?doable): >
> StableVar.java > > > /* > * Any copyright is dedicated to the Public Domain. > * https://creativecommons.org/publicdomain/zero/1.0/ > */ > > import java.util.NoSuchElementException; > import java.util.function.Supplier; > > import org.jspecify.annotations.NullMarked; > import org.jspecify.annotations.Nullable; > > import static java.lang.System.identityHashCode; > import static java.util.Objects.requireNonNull; > > /// Horrible awful hack to get access to raw stable values in JDK 26+. > @NullMarked > public sealed interface StableVar permits StableHacks.StableVarImpl { > boolean trySet(final T contents) throws NullPointerException, IllegalStateException; > @Nullable T orNull(); > T orElse(final T other) throws NullPointerException; > T orElseThrow() throws NoSuchElementException; > boolean isSet(); > T orElseSet(final Supplier supplier) throws NullPointerException, IllegalStateException; > void setOrThrow(final T contents) throws NullPointerException, IllegalStateException; > > static StableVar of() { > return StableHacks.newInstance(); > } > } > > /// Encapsulates the actual implementation of `StableValue` on `LazyConstant` > /// > /// @author ExE Boss > @NullMarked > /*package*/ final @Namespace class StableHacks { > private StableHacks() throws InstantiationException { throw new InstantiationException(StableHacks.class.getName()); } > > private static final String UNSET_SUFFIX = ".unset"; > private static final Object UNSET = new Object() { > @Override > public int hashCode() { > return 0; > } > > @Override > public String toString() { > return "unset"; > } > }; > > private static final ScopedValue SCOPE = ScopedValue.newInstance(); > private static final Supplier SCOPE_GETTER = SCOPE::get; > > /*package*/ static final StableVarImpl newInstance() { > return new StableValue<>(); > } > > /*package*/ sealed interface StableVarImpl extends StableVar { > } > > private record StableValue( > // Implemented as a record so that the JVM treats this as a trusted final field > // even when `-XX:+TrustFinalNonStaticFields` is not set > LazyConstant contents > ) implements StableVarImpl { > @SuppressWarnings("unchecked") > private StableValue() { > this(LazyConstant.of((Supplier) SCOPE_GETTER)); > } > > private StableValue { > if (contents.isInitialized()) throw new InternalError(); > } > > @SuppressWarnings("unchecked") > private fi... Hi @ExE-Boss, this new JEP describes how this functionality will be provided in the future: > Lazy constants cover the common, high-level use cases for lazy initialization. In the future we might consider providing stable access semantics directly, at a lower level, for reference, array, and primitive fields. This would address, for example, use cases where the computing function associated with a lazy constant is not known at construction. This would be necessary, as there are usage patterns (such as nominal descriptors in ClassFile API) that would benefit from multiple assignment and a stable promoted read. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3368317631 From duke at openjdk.org Mon Oct 13 11:51:05 2025 From: duke at openjdk.org (Burning_TNT) Date: Mon, 13 Oct 2025 11:51:05 GMT Subject: RFR: 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. It's essential to provide a low-level API as those in StableValue. Completely migrating to factory pattern may forcing users to build their own LazyConstant wrapper as ExeBoss has down above. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3369054838 From pminborg at openjdk.org Mon Oct 13 11:51:05 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 11:51:05 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: <5N4q67er51rXJ8E1oqNY4gCowyJ_K4x1SCeWncz1dFY=.2fe20197-fffe-467f-a1af-5816594c7e78@github.com> 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. > I?m?gonna?miss **Stable?Values**, as?it?has some?use?cases which?aren?t?served by?**Lazy?Constants**, and?on?which I?depend?on in?some of?my?code, so?I?m stuck?with using?regular non?`final`?fields. > > Also, in the [JEP?526](https://openjdk.org/jeps/526)?table under ?[Flexible?initialization with?lazy?constants](https://openjdk.org/jeps/526#Flexible-initialization-with-lazy-constants)?: > > > Update count > > Update location > > Constant folding? > > Concurrent updates? > > > > > > > > > > `final` field > > 1 > > Constructor or static initializer > > Yes > > No > > > > > > `LazyConstant` > > [0, 1] > > Anywhere > > Yes, after initialization > > Yes, by winner > > > > > > Non-`final` field > > [0, ?) > > Anywhere > > No > > Yes > > The??Update?location? of?`LazyConstant` shouldn?t?be??Anywhere?, as?that?was only?accurate for?`StableValue`, but?not for?`LazyConstant`, which?is?updated by?calling the?passed `Supplier`. > > Similarly, concurrent?updates are?prevented for?`LazyConstant`s by?using `synchronized?(this)`. I've updated the JEP. Thanks for pointing out this. Let me know what you think about the new text. We are exploring better ways to provide low-level, imperative, lazy constant/stable value fields. This work will be done outside the current JEP. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3396693041 PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3397160926 From duke at openjdk.org Mon Oct 13 11:51:06 2025 From: duke at openjdk.org (ExE Boss) Date: Mon, 13 Oct 2025 11:51:06 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: <5N4q67er51rXJ8E1oqNY4gCowyJ_K4x1SCeWncz1dFY=.2fe20197-fffe-467f-a1af-5816594c7e78@github.com> References: <5N4q67er51rXJ8E1oqNY4gCowyJ_K4x1SCeWncz1dFY=.2fe20197-fffe-467f-a1af-5816594c7e78@github.com> Message-ID: On Mon, 13 Oct 2025 09:49:16 GMT, Per Minborg wrote: > I've updated the JEP. Thanks for pointing out this. Let me know what you think about the new text. The?change was?made to?the?wrong?row (?Non?`final`?field? instead of??`LazyConstant`?). ------------- PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3396866550 From fandreuzzi at openjdk.org Mon Oct 13 11:51:09 2025 From: fandreuzzi at openjdk.org (Francesco Andreuzzi) Date: Mon, 13 Oct 2025 11:51:09 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: <9oTBJDVY4LhEXsE4tVJAItdEvmaA3YcZ0BbUrw7M9uk=.86f99b3a-fbb2-4ce4-916d-e0487fce4211@github.com> 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. src/java.base/share/classes/java/lang/LazyConstant.java line 166: > 164: * > 165: *

Performance

> 166: * As a lazy constant can never change after it has been initialized. Therefore, Suggestion: * A lazy constant can never change after it has been initialized. Therefore, src/java.base/share/classes/java/util/LazyCollections.java line 80: > 78: } > 79: > 80: @Override public boolean isEmpty() { return size == 0;} Suggestion: @Override public boolean isEmpty() { return size == 0; } ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2399059426 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2399074220 From duke at openjdk.org Mon Oct 13 11:51:10 2025 From: duke at openjdk.org (Kerman) Date: Mon, 13 Oct 2025 11:51:10 GMT Subject: RFR: 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. src/java.base/share/classes/java/util/Optional.java line 74: > 72: * If non-null, the value; if null, indicates no value is present > 73: */ > 74: @Stable Shouldn?t this also add a null sentinel to allow the folding of the empty case? Or is that irrelevant because empty would be the terminator of a chain. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2399352909 From liach at openjdk.org Mon Oct 13 11:51:11 2025 From: liach at openjdk.org (Chen Liang) Date: Mon, 13 Oct 2025 11:51:11 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: <-lErHk2PzyJCaPQGrEwCt3nObTrTHs7_p53eBXspUGE=.50dc2375-8769-49a5-9308-ab40132bbd19@github.com> On Thu, 2 Oct 2025 16:16:44 GMT, Kerman 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. > > src/java.base/share/classes/java/util/Optional.java line 74: > >> 72: * If non-null, the value; if null, indicates no value is present >> 73: */ >> 74: @Stable > > Shouldn?t this also add a null sentinel to allow the folding of the empty case? Or is that irrelevant because empty would be the terminator of a chain. 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) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2403729792 From pminborg at openjdk.org Mon Oct 13 11:51:11 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 11:51:11 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: <-lErHk2PzyJCaPQGrEwCt3nObTrTHs7_p53eBXspUGE=.50dc2375-8769-49a5-9308-ab40132bbd19@github.com> References: <-lErHk2PzyJCaPQGrEwCt3nObTrTHs7_p53eBXspUGE=.50dc2375-8769-49a5-9308-ab40132bbd19@github.com> Message-ID: On Sat, 4 Oct 2025 04:13:05 GMT, Chen Liang wrote: >> src/java.base/share/classes/java/util/Optional.java line 74: >> >>> 72: * If non-null, the value; if null, indicates no value is present >>> 73: */ >>> 74: @Stable >> >> Shouldn?t this also add a null sentinel to allow the folding of the empty case? Or is that irrelevant because empty would be the terminator of a chain. > > 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. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426044826 From liach at openjdk.org Mon Oct 13 11:51:13 2025 From: liach at openjdk.org (Chen Liang) Date: Mon, 13 Oct 2025 11:51:13 GMT Subject: RFR: 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. src/java.base/share/classes/jdk/internal/lang/LazyConstantImpl.java line 171: > 169: > 170: public static LazyConstantImpl ofLazy(Supplier computingFunction) { > 171: return new LazyConstantImpl<>(computingFunction); We might return the function if it is already a LazyConstantImpl. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2399678324 From duke at openjdk.org Mon Oct 13 11:51:14 2025 From: duke at openjdk.org (Jefferson Quesado) Date: Mon, 13 Oct 2025 11:51:14 GMT Subject: RFR: 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. src/java.base/share/classes/sun/nio/ch/Net.java line 99: > 97: } > 98: > 99: private static final LazyConstant SHUTDOWN_WRITE_BEFORE_CLOSE = LazyConstant.of(new Supplier() { I wonder if there is a reason for not using `BooleanSupplier`. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2399205774 From liach at openjdk.org Mon Oct 13 11:51:15 2025 From: liach at openjdk.org (Chen Liang) Date: Mon, 13 Oct 2025 11:51:15 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 15:21:37 GMT, Jefferson Quesado 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. > > src/java.base/share/classes/sun/nio/ch/Net.java line 99: > >> 97: } >> 98: >> 99: private static final LazyConstant SHUTDOWN_WRITE_BEFORE_CLOSE = LazyConstant.of(new Supplier() { > > I wonder if there is a reason for not using `BooleanSupplier`. Unfortunately, BooleanSupplier does not extend Supplier. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2403730001 From mcimadamore at openjdk.org Mon Oct 13 13:08:03 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:08:03 GMT Subject: RFR: 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. test/jdk/java/lang/LazyConstant/DemoImperativeTest.java line 25: > 23: > 24: /* @test > 25: * @summary Demo of an imperative stable value based on a lazy constant Should this summary be updated (and. some of the classes defined here) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426297364 From mcimadamore at openjdk.org Mon Oct 13 13:20:38 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:20:38 GMT Subject: RFR: 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. src/java.base/share/classes/java/util/LazyCollections.java line 255: > 253: } > 254: > 255: interface LenientList extends List { Ok, this seems needed to give access to `getAcquire` from sublists created from other sublists... src/java.base/share/classes/java/util/LazyCollections.java line 360: > 358: > 359: @Stable > 360: private final Set keySet; I believe putting the field in here might cause some redundancies -- for instance LazyMap extends this class and addss a `Map`, from which you can clearly derive the key set... ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426326166 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426329562 From mcimadamore at openjdk.org Mon Oct 13 13:30:34 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:30:34 GMT Subject: RFR: 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. src/java.base/share/classes/java/lang/LazyConstant.java line 42: > 40: > 41: /** > 42: * A lazy constant is a deferred, shallowly immutable constant to be computed at It seems like the javadoc is a snapshot of an earlier version of the JEP where the word "content" was replaced with "constant". I think we should go back to "content" and say (as we did for stable values) that a "A lazy constant is a holder of contents that can be set at most once." ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426358262 From mcimadamore at openjdk.org Mon Oct 13 13:34:33 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:34:33 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: <56kNzRwD6WRl9bHJUKb-YU1TuN6Tha_crXrwvfb-EmU=.c601a0b2-a66f-4d7f-9952-d235ee935fb1@github.com> 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. src/java.base/share/classes/java/lang/LazyConstant.java line 98: > 96: * constant is not initialized. > 97: *

> 98: * If the computing function throws any unchecked exception or Error, that Throwable add some code blocks around `Error` and `Throwable` ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426369216 From mcimadamore at openjdk.org Mon Oct 13 13:40:54 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:40:54 GMT Subject: RFR: 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. src/java.base/share/classes/java/lang/LazyConstant.java line 155: > 153: * {@code final} fields of any newly created objects, are safely published. > 154: *

> 155: * The computing function runs on the caller?s thread. Here you might define "we call that thread the computing thread" -- this might be useful when defining other concepts in this section (maybe) src/java.base/share/classes/java/lang/LazyConstant.java line 157: > 155: * The computing function runs on the caller?s thread. > 156: *

> 157: * If a thread that is blocked by another computing thread is interrupted, this is not I'm not sure I understand what you mean in this para src/java.base/share/classes/java/lang/LazyConstant.java line 172: > 170: * (e.g. in cases where the lazy constant itself is stored in a > 171: * {@code static final} field) or forms a trusted chain to such a VM constant via > 172: * one or more layers of a {@linkplain Record record} fields or final fields one or more layers of "trusted" fields -- then in parenthesis you say what these "trusted" fields are. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426383095 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426379186 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426387301 From mcimadamore at openjdk.org Mon Oct 13 13:40:56 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:40:56 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 13:35:21 GMT, Maurizio Cimadamore 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. > > src/java.base/share/classes/java/lang/LazyConstant.java line 157: > >> 155: * The computing function runs on the caller?s thread. >> 156: *

>> 157: * If a thread that is blocked by another computing thread is interrupted, this is not > > I'm not sure I understand what you mean in this para E.g. "thread that is blocked by another computing thread". Did you mean to say "if the thread running the computing function is interrupted"? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426381677 From mcimadamore at openjdk.org Mon Oct 13 13:46:48 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:46:48 GMT Subject: RFR: 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. src/java.base/share/classes/java/lang/LazyConstant.java line 188: > 186: * arbitrary depth can be used, which provides constant components. > 187: * More generally, a lazy constant can hold other lazy constants of > 188: * arbitrary depth and still provide transitive constancy. I'm not sure the term "constancy" is common to mean constant-ness. I think it might be better to use the term "constant-folding" -- and then define "constant-folding" in the above "performance" section: > A lazy constant can never change after it has been initialized. Therefore, > a JVM implementation may, for an initialized lazy constant, elide all future reads > of that lazy constant, and instead directly use any constant that it has previously > observed Then you can add "we call this optimization constant-folding". src/java.base/share/classes/java/lang/LazyConstant.java line 192: > 190: * The {@code LazyConstant} type is not {@link Serializable}. > 191: *

> 192: * It is not recommended putting lazy constants into equality-based collections Not sure what you mean here. It seems like the javadoc for `equals` says that it triggers initialization, so it should be ok? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426397976 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426402669 From pminborg at openjdk.org Mon Oct 13 13:46:51 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 13:46:51 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 13:17:37 GMT, Maurizio Cimadamore 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. > > src/java.base/share/classes/java/util/LazyCollections.java line 360: > >> 358: >> 359: @Stable >> 360: private final Set keySet; > > I believe putting the field in here might cause some redundancies -- for instance LazyMap extends this class and addss a `Map`, from which you can clearly derive the key set... It is true that `AbstractMap` already contains a `keySet` field. If we annotate `AbstractMap.keySet` with `@Stable` (which seems ok to do), we can get rid of this field. A note here is that eventually, we would like to get rid of all the fields in `AbstractMap`. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426399337 From mcimadamore at openjdk.org Mon Oct 13 13:50:07 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:50:07 GMT Subject: RFR: 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. src/java.base/share/classes/java/lang/LazyConstant.java line 276: > 274: * this method might block or throw. > 275: * > 276: * @implSpec The order of potential initialization triggering is specified as: Do we really need to specify this? src/java.base/share/classes/java/lang/LazyConstant.java line 312: > 310: String toString(); > 311: > 312: // Factories Suggestion: // Factory ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426409576 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426412926 From pminborg at openjdk.org Mon Oct 13 13:54:44 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 13:54:44 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v2] In-Reply-To: References: Message-ID: <90jKH5-Bb3vf27uhLPOUtgmYmZRFdH1voVYr8kIR__I=.2aff8cb2-38be-4dd3-a1df-e3f8a7a90542@github.com> > 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: Remove redundant field ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/3e287031..0978179a Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=00-01 Stats: 7 lines in 2 files changed: 3 ins; 3 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 pminborg at openjdk.org Mon Oct 13 14:03:37 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 14:03:37 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v3] 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 links around Error and Throwable ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/0978179a..5770e033 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=01-02 Stats: 5 lines in 1 file changed: 0 ins; 0 del; 5 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 Oct 13 14:03:41 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 14:03:41 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v3] In-Reply-To: References: Message-ID: <0kU7XwB4vVkXnZLTj79Gen7puX7sPTKNfZwkf3I1wpM=.840e45e2-87bb-41ad-a4be-8d474458559d@github.com> On Mon, 13 Oct 2025 13:36:19 GMT, Maurizio Cimadamore wrote: >> src/java.base/share/classes/java/lang/LazyConstant.java line 157: >> >>> 155: * The computing function runs on the caller?s thread. >>> 156: *

>>> 157: * If a thread that is blocked by another computing thread is interrupted, this is not >> >> I'm not sure I understand what you mean in this para > > E.g. "thread that is blocked by another computing thread". Did you mean to say "if the thread running the computing function is interrupted"? If a thread `A` won the race and invokes the computing function, and another thread `B` comes along while computation takes place by `A`, then interrupting thread `B` will not have any effect. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426445641 From kfarrell at openjdk.org Mon Oct 13 14:07:33 2025 From: kfarrell at openjdk.org (Kieran Farrell) Date: Mon, 13 Oct 2025 14:07:33 GMT Subject: [jdk25] RFR: 8369184: SimpleTimeZone equals() Returns True for Unequal Instances with Different hashCode Values Message-ID: Clean backport ------------- Commit messages: - Backport 37b725d9c12834358a562e6c03fb7f566d639ca5 Changes: https://git.openjdk.org/jdk/pull/27772/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27772&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8369184 Stats: 102 lines in 2 files changed: 94 ins; 0 del; 8 mod Patch: https://git.openjdk.org/jdk/pull/27772.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27772/head:pull/27772 PR: https://git.openjdk.org/jdk/pull/27772 From pminborg at openjdk.org Mon Oct 13 14:13:42 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 14:13:42 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v4] 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: Reprhase text around the computing thread ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/5770e033..47af4307 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=02-03 Stats: 13 lines in 1 file changed: 1 ins; 2 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 Oct 13 14:18:53 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 14:18:53 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v5] 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: Rephrase trusted field text ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/47af4307..ea14b8f9 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=03-04 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 Oct 13 14:22:13 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 14:22:13 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v6] In-Reply-To: References: Message-ID: <5EAP5ubicOh_odm_aPlWJZbDQTuV0AIRs-fHlW7jTlc=.86692372-8a21-49dc-a453-4dbeef84d242@github.com> > 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: Define constant folding ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/ea14b8f9..e25eeb9b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=04-05 Stats: 7 lines in 1 file changed: 1 ins; 0 del; 6 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 Oct 13 14:33:06 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 14:33:06 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v7] 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: Update src/java.base/share/classes/java/lang/LazyConstant.java Co-authored-by: Maurizio Cimadamore <54672762+mcimadamore at users.noreply.github.com> ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/e25eeb9b..5845a7a5 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=06 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=05-06 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 Oct 13 14:33:08 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 14:33:08 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v6] In-Reply-To: <5EAP5ubicOh_odm_aPlWJZbDQTuV0AIRs-fHlW7jTlc=.86692372-8a21-49dc-a453-4dbeef84d242@github.com> References: <5EAP5ubicOh_odm_aPlWJZbDQTuV0AIRs-fHlW7jTlc=.86692372-8a21-49dc-a453-4dbeef84d242@github.com> Message-ID: On Mon, 13 Oct 2025 14:22:13 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: > > Define constant folding src/java.base/share/classes/java/lang/LazyConstant.java line 156: > 154: * {@code final} fields of any newly created objects, are safely published. > 155: *

> 156: * If the computing thread or any thread that is blocked by the computing thread My worry here is that when we say "any thread that is blocked" we really meany "any thread". But in reality this javadoc only refers to threads that are trying to call `get` and end up blocked because some other thread won the race. E.g. if a thread is blocked by the computing thread for any other reason, we don't know whether interrupting that thread will result in an `InterruptedException` ? I think it might be worth simplifying this a bit, starting with the property you want to assert: > Thread interruption does not cancel initialization of a lazy constant. In other words, if the computing thread is > interrupted, `LazyConstant::get` doesn't clear the interrupted thread?s status is not cleared, nor does it throw > an `InterruptedException`. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426515394 From pminborg at openjdk.org Mon Oct 13 14:33:10 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 14:33:10 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v7] In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 13:44:07 GMT, Maurizio Cimadamore wrote: >> Per Minborg has updated the pull request incrementally with one additional commit since the last revision: >> >> Update src/java.base/share/classes/java/lang/LazyConstant.java >> >> Co-authored-by: Maurizio Cimadamore <54672762+mcimadamore at users.noreply.github.com> > > src/java.base/share/classes/java/lang/LazyConstant.java line 192: > >> 190: * The {@code LazyConstant} type is not {@link Serializable}. >> 191: *

>> 192: * It is not recommended putting lazy constants into equality-based collections > > Not sure what you mean here. It seems like the javadoc for `equals` says that it triggers initialization, so it should be ok? Formally, it is ok, but may result in strange side effects if we, for example, put a key of type LazyConstant in a map. It will then be initialized immediately (upon `map.put()`), and the put operation can therefore have non-obvious side effects. > src/java.base/share/classes/java/lang/LazyConstant.java line 276: > >> 274: * this method might block or throw. >> 275: * >> 276: * @implSpec The order of potential initialization triggering is specified as: > > Do we really need to specify this? This is a corner case, but we might have two uninitialized LCs. The order in which they get computed might be significant (e.g., they operate on shared data structures). ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426507366 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426513556 From mcimadamore at openjdk.org Mon Oct 13 14:33:13 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 14:33:13 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v7] In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 14:25:58 GMT, Per Minborg wrote: >> src/java.base/share/classes/java/lang/LazyConstant.java line 276: >> >>> 274: * this method might block or throw. >>> 275: * >>> 276: * @implSpec The order of potential initialization triggering is specified as: >> >> Do we really need to specify this? > > This is a corner case, but we might have two uninitialized LCs. The order in which they get computed might be significant (e.g., they operate on shared data structures). I understand that the order might be significant -- but I still wonder if we should specify that order. This seems to add constraints to the implementation. Do we really want clients to rely on the order in which lazy constants are initialized when calling `equals` ? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426522315 From mcimadamore at openjdk.org Mon Oct 13 14:37:27 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 14:37:27 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v7] In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 14:23:40 GMT, Per Minborg wrote: >> src/java.base/share/classes/java/lang/LazyConstant.java line 192: >> >>> 190: * The {@code LazyConstant} type is not {@link Serializable}. >>> 191: *

>>> 192: * It is not recommended putting lazy constants into equality-based collections >> >> Not sure what you mean here. It seems like the javadoc for `equals` says that it triggers initialization, so it should be ok? > > Formally, it is ok, but may result in strange side effects if we, for example, put a key of type LazyConstant in a map. It will then be initialized immediately (upon `map.put()`), and the put operation can therefore have non-obvious side effects. I think it would be better to link to `equals` more explicitly -- e.g. "As equals and hashCode might trigger the initialization of a lazy constant, it is recommended to avoid storing lazy constants into equality-based collections (or similar constructs) as their addition (e.g. via `Map::put`, or `Set::add`) might result in subtle side-effects). ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426535831 From mcimadamore at openjdk.org Mon Oct 13 14:44:09 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 14:44:09 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v7] In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 14:33:06 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: > > Update src/java.base/share/classes/java/lang/LazyConstant.java > > Co-authored-by: Maurizio Cimadamore <54672762+mcimadamore at users.noreply.github.com> src/java.base/share/classes/java/lang/LazyConstant.java line 287: > 285: */ > 286: @Override > 287: boolean equals(Object obj); There is a tension here (same for hashCode). A lazy constant is a mutable cell that can be updated only once, given some computing function. When you compare two lazy constants, you can either compare the mutable cell (e.g. the pointer to the memory location where the constant will be eventually stored), or you can compare the constants. Here, the javadoc decides to opt for comparing the constants -- but this might be problematic, as now `equals` can throw exceptions too (and/or result in blocking, as you say in the javadoc). So, I'm not too sure what's the best option here -- do we have an idea of how frequent it is to want to compare two lazy constants "by value" ? (for reference, we have no precedent for this: `ClassValue`, `ScopedValue` and `ThreadLocal` do not redefine equals/hashCode). ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426553275 From jlu at openjdk.org Mon Oct 13 16:14:31 2025 From: jlu at openjdk.org (Justin Lu) Date: Mon, 13 Oct 2025 16:14:31 GMT Subject: Integrated: 8369452: Locale.Builder.setLanguageTag(String) does not clear on empty or null String In-Reply-To: References: Message-ID: On Thu, 9 Oct 2025 18:12:58 GMT, Justin Lu wrote: > Please review this PR which corrects the behavior of `Locale.Builder.setLanguageTag(String)` on the null and empty String case. > > This method is specified as follows, > >> Null and the empty string cause the builder to be reset > > Currently, NPE is thrown for a null tag, and ILE is thrown for an empty String. They are both corrected to not throw, and instead reset the state of the `Locale.Builder`. This pull request has now been integrated. Changeset: 1d6cafdc Author: Justin Lu URL: https://git.openjdk.org/jdk/commit/1d6cafdc5244960ddec2fd82b8454c6c3cafe022 Stats: 27 lines in 2 files changed: 22 ins; 0 del; 5 mod 8369452: Locale.Builder.setLanguageTag(String) does not clear on empty or null String Reviewed-by: naoto ------------- PR: https://git.openjdk.org/jdk/pull/27734 From duke at openjdk.org Mon Oct 13 16:52:00 2025 From: duke at openjdk.org (ExE Boss) Date: Mon, 13 Oct 2025 16:52:00 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v2] In-Reply-To: <90jKH5-Bb3vf27uhLPOUtgmYmZRFdH1voVYr8kIR__I=.2aff8cb2-38be-4dd3-a1df-e3f8a7a90542@github.com> References: <90jKH5-Bb3vf27uhLPOUtgmYmZRFdH1voVYr8kIR__I=.2aff8cb2-38be-4dd3-a1df-e3f8a7a90542@github.com> Message-ID: On Mon, 13 Oct 2025 13:54:44 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: > > Remove redundant field src/java.base/share/classes/java/util/AbstractMap.java line 335: > 333: */ > 334: @Stable > 335: transient Set keySet; Are?all?uses of?this?field in?`java.util` able?to?handle the?`@Stable`ness of?this?field correctly? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426844190 From liach at openjdk.org Mon Oct 13 18:49:05 2025 From: liach at openjdk.org (Chen Liang) Date: Mon, 13 Oct 2025 18:49:05 GMT Subject: [jdk25] RFR: 8369184: SimpleTimeZone equals() Returns True for Unequal Instances with Different hashCode Values In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 13:58:04 GMT, Kieran Farrell wrote: > Clean backport Hi, I don't think this is the right branch to backport to - you should backport to the master branch of jdk25u repo. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27772#issuecomment-3398668419 From kfarrell at openjdk.org Mon Oct 13 19:34:14 2025 From: kfarrell at openjdk.org (Kieran Farrell) Date: Mon, 13 Oct 2025 19:34:14 GMT Subject: [jdk25] Withdrawn: 8369184: SimpleTimeZone equals() Returns True for Unequal Instances with Different hashCode Values In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 13:58:04 GMT, Kieran Farrell wrote: > Clean backport This pull request has been closed without being integrated. ------------- PR: https://git.openjdk.org/jdk/pull/27772 From jlu at openjdk.org Mon Oct 13 21:27:14 2025 From: jlu at openjdk.org (Justin Lu) Date: Mon, 13 Oct 2025 21:27:14 GMT Subject: RFR: 8369590: LocaleEnhanceTest has incorrectly passing test case Message-ID: This PR corrects _test/jdk/java/util/Locale/LocaleEnhanceTest.java_, which has two test cases under `testBuilderSetLanguageTag()` which accidentally pass. One checks that Locale.setLanguageTag(String) throws ILE for duplicate extensions and the other for duplicate U-extension keys. The test cases are updated to actually test the provided code. When the test cases are fixed, they now fail. Fixing the behavior to match the expectation of those test cases is consistent with the specification. >From `Locale.forLanguageTag(String)`, > > *

If the specified language tag contains any ill-formed subtags, > * the first such subtag and all following subtags are ignored. Compare > * to {@link Locale.Builder#setLanguageTag(String)} which throws an exception > * in this case. and the RFC specification > Each singleton subtag MUST appear at most one time in each tag > (other than as a private use subtag). That is, singleton subtags > MUST NOT be repeated. For example, the tag "en-a-bbb-a-ccc" is > invalid because the subtag 'a' appears twice. Since duplicate extensions (and Unicode keys/attributes) are invalid, throwing `IllformedLocaleException` in (the strict) `Locale.Builder` and ignoring in (the lenient) `Locale.forLanguageTag` for such tags would be appropriate. This PR updates the implementation as such. ------------- Commit messages: - Add duplicate checking for Locale.Builder.setLanguageTag(String) - Add duplicate U extension attributes test case - Remove testing classes in favor or JUnit (which fixes unintentional passing) Changes: https://git.openjdk.org/jdk/pull/27775/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27775&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8369590 Stats: 686 lines in 4 files changed: 75 ins; 169 del; 442 mod Patch: https://git.openjdk.org/jdk/pull/27775.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27775/head:pull/27775 PR: https://git.openjdk.org/jdk/pull/27775 From jlu at openjdk.org Mon Oct 13 21:27:15 2025 From: jlu at openjdk.org (Justin Lu) Date: Mon, 13 Oct 2025 21:27:15 GMT Subject: RFR: 8369590: LocaleEnhanceTest has incorrectly passing test case In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 20:55:45 GMT, Justin Lu wrote: > This PR corrects _test/jdk/java/util/Locale/LocaleEnhanceTest.java_, which has two test cases under `testBuilderSetLanguageTag()` which accidentally pass. One checks that Locale.setLanguageTag(String) throws ILE for duplicate extensions and the other for duplicate U-extension keys. The test cases are updated to actually test the provided code. When the test cases are fixed, they now fail. > > Fixing the behavior to match the expectation of those test cases is consistent with the specification. > > From `Locale.forLanguageTag(String)`, > >> >> *

If the specified language tag contains any ill-formed subtags, >> * the first such subtag and all following subtags are ignored. Compare >> * to {@link Locale.Builder#setLanguageTag(String)} which throws an exception >> * in this case. > > and the RFC specification > >> Each singleton subtag MUST appear at most one time in each tag >> (other than as a private use subtag). That is, singleton subtags >> MUST NOT be repeated. For example, the tag "en-a-bbb-a-ccc" is >> invalid because the subtag 'a' appears twice. > > Since duplicate extensions (and Unicode keys/attributes) are invalid, throwing `IllformedLocaleException` in (the strict) `Locale.Builder` and ignoring in (the lenient) `Locale.forLanguageTag` for such tags would be appropriate. This PR updates the implementation as such. src/java.base/share/classes/sun/util/locale/InternalLocaleBuilder.java line 212: > 210: > 211: if (UnicodeLocaleExtension.isSingletonChar(key.value())) { > 212: setUnicodeLocaleExtension(val, true); This code is called under `Locale.Builder.setExtension(char, String)`, which remains lenient for duplicate U-extension keys and attributes since this existing behavior is confirmed as a test case in _LocaleEnhanceTest_, // redundant locale extensions are ignored result = builder .clear() .setExtension('u', "nu-thai-NU-chinese-xx-1234") .build() .toLanguageTag(); assertEquals("duplicate keys", "und-u-nu-thai-xx-1234", result); test/jdk/java/util/Locale/LocaleEnhanceTest.java line 767: > 765: > 766: // redundant Unicode locale extension keys within an Unicode locale extension cause a failure > 767: new BuilderILE() { public void call() { b.setLanguageTag("und-u-nu-thai-NU-chinese-xx-1234"); }}; These lines both relied on the `BuilderILE` testing class. However, since they provided no args to the ctor, the `run()` call does not actually execute the provided code under `call()`. `BuilderILE` and the other helper testing classes are replaced with JUnit in https://github.com/openjdk/jdk/pull/27775/commits/f4927421ad3f7b2647ecd29059e2e64683b9f270. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27775#discussion_r2427333112 PR Review Comment: https://git.openjdk.org/jdk/pull/27775#discussion_r2427320692 From jlu at openjdk.org Mon Oct 13 21:51:32 2025 From: jlu at openjdk.org (Justin Lu) Date: Mon, 13 Oct 2025 21:51:32 GMT Subject: RFR: 8369590: LocaleEnhanceTest has incorrectly passing test case [v2] In-Reply-To: References: Message-ID: <11DDueNxPmVaTZ2u9WMchm4kWfC5Ims83jkGE3S2RXQ=.03c79e51-6977-45c0-ae6f-c55e03d62598@github.com> > This PR corrects _test/jdk/java/util/Locale/LocaleEnhanceTest.java_, which has two test cases under `testBuilderSetLanguageTag()` which accidentally pass. One checks that Locale.setLanguageTag(String) throws ILE for duplicate extensions and the other for duplicate U-extension keys. The test cases are updated to actually test the provided code. When the test cases are fixed, they now fail. > > Fixing the behavior to match the expectation of those test cases is consistent with the specification. > > From `Locale.forLanguageTag(String)`, > >> >> *

If the specified language tag contains any ill-formed subtags, >> * the first such subtag and all following subtags are ignored. Compare >> * to {@link Locale.Builder#setLanguageTag(String)} which throws an exception >> * in this case. > > and the RFC specification > >> Each singleton subtag MUST appear at most one time in each tag >> (other than as a private use subtag). That is, singleton subtags >> MUST NOT be repeated. For example, the tag "en-a-bbb-a-ccc" is >> invalid because the subtag 'a' appears twice. > > Since duplicate extensions (and Unicode keys/attributes) are invalid, throwing `IllformedLocaleException` in (the strict) `Locale.Builder` and ignoring in (the lenient) `Locale.forLanguageTag` for such tags would be appropriate. This PR updates the implementation as such. Justin Lu has updated the pull request incrementally with one additional commit since the last revision: Adding test case to confirm duplicate U-extension attributes for setExtension(char, String) ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27775/files - new: https://git.openjdk.org/jdk/pull/27775/files/524dd361..f73a15ae Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27775&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27775&range=00-01 Stats: 8 lines in 1 file changed: 8 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/27775.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27775/head:pull/27775 PR: https://git.openjdk.org/jdk/pull/27775 From naoto at openjdk.org Mon Oct 13 22:29:05 2025 From: naoto at openjdk.org (Naoto Sato) Date: Mon, 13 Oct 2025 22:29:05 GMT Subject: RFR: 8369590: LocaleEnhanceTest has incorrectly passing test case [v2] In-Reply-To: <11DDueNxPmVaTZ2u9WMchm4kWfC5Ims83jkGE3S2RXQ=.03c79e51-6977-45c0-ae6f-c55e03d62598@github.com> References: <11DDueNxPmVaTZ2u9WMchm4kWfC5Ims83jkGE3S2RXQ=.03c79e51-6977-45c0-ae6f-c55e03d62598@github.com> Message-ID: On Mon, 13 Oct 2025 21:51:32 GMT, Justin Lu wrote: >> This PR corrects _test/jdk/java/util/Locale/LocaleEnhanceTest.java_, which has two test cases under `testBuilderSetLanguageTag()` which accidentally pass. One checks that Locale.setLanguageTag(String) throws ILE for duplicate extensions and the other for duplicate U-extension keys. The test cases are updated to actually test the provided code. When the test cases are fixed, they now fail. >> >> Fixing the behavior to match the expectation of those test cases is consistent with the specification. >> >> From `Locale.forLanguageTag(String)`, >> >>> >>> *

If the specified language tag contains any ill-formed subtags, >>> * the first such subtag and all following subtags are ignored. Compare >>> * to {@link Locale.Builder#setLanguageTag(String)} which throws an exception >>> * in this case. >> >> and the RFC specification >> >>> Each singleton subtag MUST appear at most one time in each tag >>> (other than as a private use subtag). That is, singleton subtags >>> MUST NOT be repeated. For example, the tag "en-a-bbb-a-ccc" is >>> invalid because the subtag 'a' appears twice. >> >> Since duplicate extensions (and Unicode keys/attributes) are invalid, throwing `IllformedLocaleException` in (the strict) `Locale.Builder` and ignoring in (the lenient) `Locale.forLanguageTag` for such tags would be appropriate. This PR updates the implementation as such. > > Justin Lu has updated the pull request incrementally with one additional commit since the last revision: > > Adding test case to confirm duplicate U-extension attributes for setExtension(char, String) IIUC, the quote from the RFC refers to duplicate singletons. For example, it would reject something like `-u-aa-bbb-u-cc-ddd`. So I believe that rule doesn?t apply to cases like `-u-aa-bbb-AA-ccc`. I checked the `-u` extension definition in LDML but couldn?t find any description regarding duplicate keywords. That said, I think it makes sense to allow them in lenient mode and throw an exception in strict mode. Since this would introduce a behavioral change, I?d expect it to require a CSR. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27775#issuecomment-3399242375 From jlu at openjdk.org Tue Oct 14 21:11:39 2025 From: jlu at openjdk.org (Justin Lu) Date: Tue, 14 Oct 2025 21:11:39 GMT Subject: RFR: 8369590: LocaleEnhanceTest has incorrectly passing test case [v3] In-Reply-To: References: Message-ID: > This PR corrects _test/jdk/java/util/Locale/LocaleEnhanceTest.java_, which has two test cases under `testBuilderSetLanguageTag()` which accidentally pass. One checks that Locale.setLanguageTag(String) throws ILE for duplicate extensions and the other for duplicate U-extension keys. The test cases are updated to actually test the provided code. When the test cases are fixed, they now fail. > > Fixing the behavior to match the expectation of those test cases is consistent with the specification. > > From `Locale.forLanguageTag(String)`, > >> >> *

If the specified language tag contains any ill-formed subtags, >> * the first such subtag and all following subtags are ignored. Compare >> * to {@link Locale.Builder#setLanguageTag(String)} which throws an exception >> * in this case. > > and the RFC specification > >> Each singleton subtag MUST appear at most one time in each tag >> (other than as a private use subtag). That is, singleton subtags >> MUST NOT be repeated. For example, the tag "en-a-bbb-a-ccc" is >> invalid because the subtag 'a' appears twice. > > Since duplicate extensions (and Unicode keys/attributes) are invalid, throwing `IllformedLocaleException` in (the strict) `Locale.Builder` and ignoring in (the lenient) `Locale.forLanguageTag` for such tags would be appropriate. This PR updates the implementation as such. Justin Lu has updated the pull request incrementally with one additional commit since the last revision: Align setExtension(char, String) + spec updates ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27775/files - new: https://git.openjdk.org/jdk/pull/27775/files/f73a15ae..b3167f13 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27775&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27775&range=01-02 Stats: 32 lines in 3 files changed: 11 ins; 4 del; 17 mod Patch: https://git.openjdk.org/jdk/pull/27775.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27775/head:pull/27775 PR: https://git.openjdk.org/jdk/pull/27775 From jlu at openjdk.org Tue Oct 14 21:11:41 2025 From: jlu at openjdk.org (Justin Lu) Date: Tue, 14 Oct 2025 21:11:41 GMT Subject: RFR: 8369590: LocaleEnhanceTest has incorrectly passing test case [v2] In-Reply-To: References: <11DDueNxPmVaTZ2u9WMchm4kWfC5Ims83jkGE3S2RXQ=.03c79e51-6977-45c0-ae6f-c55e03d62598@github.com> Message-ID: On Mon, 13 Oct 2025 22:26:07 GMT, Naoto Sato wrote: >> Justin Lu has updated the pull request incrementally with one additional commit since the last revision: >> >> Adding test case to confirm duplicate U-extension attributes for setExtension(char, String) > > IIUC, the quote from the RFC refers to duplicate singletons. For example, it would reject something like `-u-aa-bbb-u-cc-ddd`. So I believe that rule doesn?t apply to cases like `-u-aa-bbb-AA-ccc`. I checked the `-u` extension definition in LDML but couldn?t find any description regarding duplicate keywords. > > That said, I think it makes sense to allow them in lenient mode and throw an exception in strict mode. Since this would introduce a behavioral change, I?d expect it to require a CSR. @naotoj CSR is filed and this PR is updated with the appropriate specification updates. `setExtension(char, String)` is also updated to align with `setLanguageTag(String)` on the behavior of duplicate U-extension keys and attributes as we discussed. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27775#issuecomment-3403621489 From aturbanov at openjdk.org Wed Oct 15 08:42:22 2025 From: aturbanov at openjdk.org (Andrey Turbanov) Date: Wed, 15 Oct 2025 08:42:22 GMT Subject: RFR: 8369590: LocaleEnhanceTest has incorrectly passing test case [v3] In-Reply-To: References: Message-ID: On Tue, 14 Oct 2025 21:11:39 GMT, Justin Lu wrote: >> This PR corrects _test/jdk/java/util/Locale/LocaleEnhanceTest.java_, which has two test cases under `testBuilderSetLanguageTag()` which accidentally pass. One checks that Locale.setLanguageTag(String) throws ILE for duplicate extensions and the other for duplicate U-extension keys. The test cases are updated to actually test the provided code. When the test cases are fixed, they now fail. >> >> Fixing the behavior to match the expectation of those test cases is consistent with the specification. >> >> From `Locale.forLanguageTag(String)`, >> >>> >>> *

If the specified language tag contains any ill-formed subtags, >>> * the first such subtag and all following subtags are ignored. Compare >>> * to {@link Locale.Builder#setLanguageTag(String)} which throws an exception >>> * in this case. >> >> and the RFC specification >> >>> Each singleton subtag MUST appear at most one time in each tag >>> (other than as a private use subtag). That is, singleton subtags >>> MUST NOT be repeated. For example, the tag "en-a-bbb-a-ccc" is >>> invalid because the subtag 'a' appears twice. >> >> Since duplicate extensions (and Unicode keys/attributes) are invalid, throwing `IllformedLocaleException` in (the strict) `Locale.Builder` and ignoring in (the lenient) `Locale.forLanguageTag` for such tags would be appropriate. This PR updates the implementation as such. > > Justin Lu has updated the pull request incrementally with one additional commit since the last revision: > > Align setExtension(char, String) + spec updates test/jdk/java/util/Locale/LocaleEnhanceTest.java line 1096: > 1094: // null attribute throws NPE > 1095: assertThrows(NullPointerException.class, > 1096: () -> new Builder().addUnicodeLocaleAttribute(null), "null attribute"); Suggestion: () -> new Builder().addUnicodeLocaleAttribute(null), "null attribute"); ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27775#discussion_r2431645260 From naoto at openjdk.org Wed Oct 15 17:30:53 2025 From: naoto at openjdk.org (Naoto Sato) Date: Wed, 15 Oct 2025 17:30:53 GMT Subject: RFR: 8369590: LocaleEnhanceTest has incorrectly passing test case [v3] In-Reply-To: References: Message-ID: <8UUWtXMN_CGEU_bQKvMXONleEgOgipFjFg9nKDb8ozM=.a6bfa378-8794-49e0-b61c-64da61897bed@github.com> On Tue, 14 Oct 2025 21:11:39 GMT, Justin Lu wrote: >> This PR corrects _test/jdk/java/util/Locale/LocaleEnhanceTest.java_, which has two test cases under `testBuilderSetLanguageTag()` which accidentally pass. One checks that Locale.setLanguageTag(String) throws ILE for duplicate extensions and the other for duplicate U-extension keys. The test cases are updated to actually test the provided code. When the test cases are fixed, they now fail. >> >> Fixing the behavior to match the expectation of those test cases is consistent with the specification. >> >> From `Locale.forLanguageTag(String)`, >> >>> >>> *

If the specified language tag contains any ill-formed subtags, >>> * the first such subtag and all following subtags are ignored. Compare >>> * to {@link Locale.Builder#setLanguageTag(String)} which throws an exception >>> * in this case. >> >> and the RFC specification >> >>> Each singleton subtag MUST appear at most one time in each tag >>> (other than as a private use subtag). That is, singleton subtags >>> MUST NOT be repeated. For example, the tag "en-a-bbb-a-ccc" is >>> invalid because the subtag 'a' appears twice. >> >> Since duplicate extensions (and Unicode keys/attributes) are invalid, throwing `IllformedLocaleException` in (the strict) `Locale.Builder` and ignoring in (the lenient) `Locale.forLanguageTag` for such tags would be appropriate. This PR updates the implementation as such. > > Justin Lu has updated the pull request incrementally with one additional commit since the last revision: > > Align setExtension(char, String) + spec updates LGTM. Glad to see those test clean-ups, especiallly getting rid of the proprietary test framework ------------- Marked as reviewed by naoto (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27775#pullrequestreview-3341556118 From rgiulietti at openjdk.org Wed Oct 15 18:09:33 2025 From: rgiulietti at openjdk.org (Raffaello Giulietti) Date: Wed, 15 Oct 2025 18:09:33 GMT Subject: RFR: 8341914: The j.u.Formatter doc for TemporalAccessor should be enhanced Message-ID: Doc only change. ------------- Commit messages: - 8341914: The j.u.Formatter doc for TemporalAccessor should be enhanced Changes: https://git.openjdk.org/jdk/pull/27830/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27830&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8341914 Stats: 8 lines in 1 file changed: 8 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/27830.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27830/head:pull/27830 PR: https://git.openjdk.org/jdk/pull/27830 From rgiulietti at openjdk.org Wed Oct 15 18:20:36 2025 From: rgiulietti at openjdk.org (Raffaello Giulietti) Date: Wed, 15 Oct 2025 18:20:36 GMT Subject: RFR: 8341914: The j.u.Formatter doc for TemporalAccessor should be enhanced [v2] In-Reply-To: References: Message-ID: > Doc only change. Raffaello Giulietti has updated the pull request incrementally with one additional commit since the last revision: Add the 'c' conversion as well. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27830/files - new: https://git.openjdk.org/jdk/pull/27830/files/b3c6a01a..c51f19f6 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27830&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27830&range=00-01 Stats: 4 lines in 1 file changed: 4 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/27830.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27830/head:pull/27830 PR: https://git.openjdk.org/jdk/pull/27830 From rriggs at openjdk.org Wed Oct 15 19:00:59 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Wed, 15 Oct 2025 19:00:59 GMT Subject: RFR: 8341914: The j.u.Formatter doc for TemporalAccessor should be enhanced [v2] In-Reply-To: References: Message-ID: On Wed, 15 Oct 2025 18:20:36 GMT, Raffaello Giulietti wrote: >> Doc only change. > > Raffaello Giulietti has updated the pull request incrementally with one additional commit since the last revision: > > Add the 'c' conversion as well. The PR comment should be more complete than just "doc only change". It should describe the scope and intent. It makes the emails and PR easier to grok without having to read the code. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27830#issuecomment-3407837104 From rriggs at openjdk.org Wed Oct 15 19:15:52 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Wed, 15 Oct 2025 19:15:52 GMT Subject: RFR: 8341914: The j.u.Formatter doc for TemporalAccessor should be enhanced [v2] In-Reply-To: References: Message-ID: On Wed, 15 Oct 2025 18:20:36 GMT, Raffaello Giulietti wrote: >> Doc only change. > > Raffaello Giulietti has updated the pull request incrementally with one additional commit since the last revision: > > Add the 'c' conversion as well. A bit more background would be useful here. The mention of TemporalAccessor in the context of timezone formatting characters seems out of place or too specific. It would be more appropriate to highlight that data dependent requirement in the section on Date/Time formatting. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27830#issuecomment-3407905758 From naoto at openjdk.org Wed Oct 15 19:41:28 2025 From: naoto at openjdk.org (Naoto Sato) Date: Wed, 15 Oct 2025 19:41:28 GMT Subject: RFR: 8341914: The j.u.Formatter doc for TemporalAccessor should be enhanced [v2] In-Reply-To: References: Message-ID: On Wed, 15 Oct 2025 18:20:36 GMT, Raffaello Giulietti wrote: >> Doc only change. > > Raffaello Giulietti has updated the pull request incrementally with one additional commit since the last revision: > > Add the 'c' conversion as well. Would this only apply to time zone? What if `LocalDate` is passed as a `TemporalAccessor` and the conversion requests hour or minute? Could this be more generic? ------------- PR Comment: https://git.openjdk.org/jdk/pull/27830#issuecomment-3407984637 From jlu at openjdk.org Wed Oct 15 20:37:16 2025 From: jlu at openjdk.org (Justin Lu) Date: Wed, 15 Oct 2025 20:37:16 GMT Subject: RFR: 8369590: LocaleEnhanceTest has incorrectly passing test case [v4] In-Reply-To: References: Message-ID: > This PR corrects _test/jdk/java/util/Locale/LocaleEnhanceTest.java_, which has two test cases under `testBuilderSetLanguageTag()` which accidentally pass. One checks that Locale.setLanguageTag(String) throws ILE for duplicate extensions and the other for duplicate U-extension keys. The test cases are updated to actually test the provided code. When the test cases are fixed, they now fail. > > Fixing the behavior to match the expectation of those test cases is consistent with the specification. > > From `Locale.forLanguageTag(String)`, > >> >> *

If the specified language tag contains any ill-formed subtags, >> * the first such subtag and all following subtags are ignored. Compare >> * to {@link Locale.Builder#setLanguageTag(String)} which throws an exception >> * in this case. > > and the RFC specification > >> Each singleton subtag MUST appear at most one time in each tag >> (other than as a private use subtag). That is, singleton subtags >> MUST NOT be repeated. For example, the tag "en-a-bbb-a-ccc" is >> invalid because the subtag 'a' appears twice. > > Since duplicate extensions (and Unicode keys/attributes) are invalid, throwing `IllformedLocaleException` in (the strict) `Locale.Builder` and ignoring in (the lenient) `Locale.forLanguageTag` for such tags would be appropriate. This PR updates the implementation as such. Justin Lu has updated the pull request incrementally with one additional commit since the last revision: Spacing fix in LocaleEnhanceTest.java Co-authored-by: Andrey Turbanov ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27775/files - new: https://git.openjdk.org/jdk/pull/27775/files/b3167f13..b0cfd59b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27775&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27775&range=02-03 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/27775.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27775/head:pull/27775 PR: https://git.openjdk.org/jdk/pull/27775 From rgiulietti at openjdk.org Wed Oct 15 20:49:44 2025 From: rgiulietti at openjdk.org (Raffaello Giulietti) Date: Wed, 15 Oct 2025 20:49:44 GMT Subject: RFR: 8341914: The j.u.Formatter doc for TemporalAccessor should be enhanced [v2] In-Reply-To: References: Message-ID: On Wed, 15 Oct 2025 18:20:36 GMT, Raffaello Giulietti wrote: >> Doc only change. > > Raffaello Giulietti has updated the pull request incrementally with one additional commit since the last revision: > > Add the 'c' conversion as well. The `Formatter` documentation related to dates/times has 3 tables: for times, for dates, and for "common date/time compositions". All conversion character for dates are applicable to all dates/datetimes (but not to times-only instances). Something similar should hold for conversion characters of times/datetimes: they should be applicable to all times/datetimes (and not to date-only instances). But `z` and `Z` represent an exception, as they apply only if time zone information is available. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27830#issuecomment-3408216496 From pminborg at openjdk.org Thu Oct 16 12:10:32 2025 From: pminborg at openjdk.org (Per Minborg) Date: Thu, 16 Oct 2025 12:10:32 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v7] In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 14:41:11 GMT, Maurizio Cimadamore wrote: >> Per Minborg has updated the pull request incrementally with one additional commit since the last revision: >> >> Update src/java.base/share/classes/java/lang/LazyConstant.java >> >> Co-authored-by: Maurizio Cimadamore <54672762+mcimadamore at users.noreply.github.com> > > src/java.base/share/classes/java/lang/LazyConstant.java line 287: > >> 285: */ >> 286: @Override >> 287: boolean equals(Object obj); > > There is a tension here (same for hashCode). A lazy constant is a mutable cell that can be updated only once, given some computing function. When you compare two lazy constants, you can either compare the mutable cell (e.g. the pointer to the memory location where the constant will be eventually stored), or you can compare the constants. Here, the javadoc decides to opt for comparing the constants -- but this might be problematic, as now `equals` can throw exceptions too (and/or result in blocking, as you say in the javadoc). So, I'm not too sure what's the best option here -- do we have an idea of how frequent it is to want to compare two lazy constants "by value" ? > > (for reference, we have no precedent for this: `ClassValue`, `ScopedValue` and `ThreadLocal` do not redefine equals/hashCode). I have reverted back to the default Object::hashCode and Object::equals methods ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2435655625 From pminborg at openjdk.org Thu Oct 16 12:13:46 2025 From: pminborg at openjdk.org (Per Minborg) Date: Thu, 16 Oct 2025 12:13:46 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v2] In-Reply-To: References: <90jKH5-Bb3vf27uhLPOUtgmYmZRFdH1voVYr8kIR__I=.2aff8cb2-38be-4dd3-a1df-e3f8a7a90542@github.com> Message-ID: On Mon, 13 Oct 2025 16:48:07 GMT, ExE Boss wrote: >> Per Minborg has updated the pull request incrementally with one additional commit since the last revision: >> >> Remove redundant field > > src/java.base/share/classes/java/util/AbstractMap.java line 335: > >> 333: */ >> 334: @Stable >> 335: transient Set keySet; > > Are?all?uses of?this?field in?`java.util` able?to?handle the?`@Stable`ness of?this?field correctly? That is a good question. The potentially different keySet values should be freely substitutable or else there seams to be something wrong. If they are FS, then the VM should be able to pick any. But it is a big assumption to say that *all* maps that extend AM behave in such a way. We could go back to the previous version and shadow the field. That seems safest. Note: there is work in progress to remove these fields. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2435668562 From pminborg at openjdk.org Thu Oct 16 12:23:26 2025 From: pminborg at openjdk.org (Per Minborg) Date: Thu, 16 Oct 2025 12:23:26 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v8] 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 incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 94 additional commits since the last revision: - Revert back to Object::(hashCode/equals) - Merge branch 'master' into lazy-constants - Update src/java.base/share/classes/java/lang/LazyConstant.java Co-authored-by: Maurizio Cimadamore <54672762+mcimadamore at users.noreply.github.com> - Define constant folding - Rephrase trusted field text - Reprhase text around the computing thread - Add links around Error and Throwable - Remove redundant field - Add optimization where the computing function is returned directly - Add benchmark of Optionals - ... and 84 more: https://git.openjdk.org/jdk/compare/6cbed094...8fa4a4ca ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/5845a7a5..8fa4a4ca Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=07 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=06-07 Stats: 10612 lines in 265 files changed: 5868 ins; 4190 del; 554 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 Thu Oct 16 12:33:31 2025 From: pminborg at openjdk.org (Per Minborg) Date: Thu, 16 Oct 2025 12:33:31 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v9] 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: Rephrase docs on interrupt ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/8fa4a4ca..e6268f3d Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=08 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=07-08 Stats: 4 lines in 1 file changed: 0 ins; 1 del; 3 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 Thu Oct 16 12:37:35 2025 From: pminborg at openjdk.org (Per Minborg) Date: Thu, 16 Oct 2025 12:37:35 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v10] 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: Update first javadoc sentence ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/e6268f3d..f5493909 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=09 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=08-09 Stats: 2 lines in 1 file changed: 0 ins; 1 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 pminborg at openjdk.org Thu Oct 16 12:41:56 2025 From: pminborg at openjdk.org (Per Minborg) Date: Thu, 16 Oct 2025 12:41:56 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v11] 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 test descriptions ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/f5493909..a51f221a Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=10 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=09-10 Stats: 2 lines in 2 files 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 jlu at openjdk.org Thu Oct 16 21:56:33 2025 From: jlu at openjdk.org (Justin Lu) Date: Thu, 16 Oct 2025 21:56:33 GMT Subject: RFR: 8369590: LocaleEnhanceTest has incorrectly passing test case [v5] In-Reply-To: References: Message-ID: > This PR corrects _test/jdk/java/util/Locale/LocaleEnhanceTest.java_, which has two test cases under `testBuilderSetLanguageTag()` which accidentally pass. One checks that Locale.setLanguageTag(String) throws ILE for duplicate extensions and the other for duplicate U-extension keys. The test cases are updated to actually test the provided code. When the test cases are fixed, they now fail. > > Fixing the behavior to match the expectation of those test cases is consistent with the specification. > > From `Locale.forLanguageTag(String)`, > >> >> *

If the specified language tag contains any ill-formed subtags, >> * the first such subtag and all following subtags are ignored. Compare >> * to {@link Locale.Builder#setLanguageTag(String)} which throws an exception >> * in this case. > > and the RFC specification > >> Each singleton subtag MUST appear at most one time in each tag >> (other than as a private use subtag). That is, singleton subtags >> MUST NOT be repeated. For example, the tag "en-a-bbb-a-ccc" is >> invalid because the subtag 'a' appears twice. > > Since duplicate extensions (and Unicode keys/attributes) are invalid, throwing `IllformedLocaleException` in (the strict) `Locale.Builder` and ignoring in (the lenient) `Locale.forLanguageTag` for such tags would be appropriate. This PR updates the implementation as such. Justin Lu has updated the pull request incrementally with one additional commit since the last revision: Remove impl changes. Simply update test to reflect duplicate ignoring behavior ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27775/files - new: https://git.openjdk.org/jdk/pull/27775/files/b0cfd59b..62c9aa5b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27775&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27775&range=03-04 Stats: 78 lines in 4 files changed: 4 ins; 38 del; 36 mod Patch: https://git.openjdk.org/jdk/pull/27775.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27775/head:pull/27775 PR: https://git.openjdk.org/jdk/pull/27775 From jlu at openjdk.org Thu Oct 16 21:56:34 2025 From: jlu at openjdk.org (Justin Lu) Date: Thu, 16 Oct 2025 21:56:34 GMT Subject: RFR: 8369590: LocaleEnhanceTest has incorrectly passing test case [v4] In-Reply-To: References: Message-ID: On Wed, 15 Oct 2025 20:37:16 GMT, Justin Lu wrote: >> This PR corrects _test/jdk/java/util/Locale/LocaleEnhanceTest.java_, which has two test cases under `testBuilderSetLanguageTag()` which accidentally pass. One checks that Locale.setLanguageTag(String) throws ILE for duplicate extensions and the other for duplicate U-extension keys. The test cases are updated to actually test the provided code. When the test cases are fixed, they now fail. >> >> Fixing the behavior to match the expectation of those test cases is consistent with the specification. >> >> From `Locale.forLanguageTag(String)`, >> >>> >>> *

If the specified language tag contains any ill-formed subtags, >>> * the first such subtag and all following subtags are ignored. Compare >>> * to {@link Locale.Builder#setLanguageTag(String)} which throws an exception >>> * in this case. >> >> and the RFC specification >> >>> Each singleton subtag MUST appear at most one time in each tag >>> (other than as a private use subtag). That is, singleton subtags >>> MUST NOT be repeated. For example, the tag "en-a-bbb-a-ccc" is >>> invalid because the subtag 'a' appears twice. >> >> Since duplicate extensions (and Unicode keys/attributes) are invalid, throwing `IllformedLocaleException` in (the strict) `Locale.Builder` and ignoring in (the lenient) `Locale.forLanguageTag` for such tags would be appropriate. This PR updates the implementation as such. > > Justin Lu has updated the pull request incrementally with one additional commit since the last revision: > > Spacing fix in LocaleEnhanceTest.java > > Co-authored-by: Andrey Turbanov As discussed, while it would be nice to enforce these duplicate cases, we do not guarantee validity of BCP47 tags. (Primarily, checking against the registry.) Duplicates falls under "valid", not "well-formed" and `Locale.Builder` should not have partial conformance of validity. Rather, the faulty test case should be updated to reflect the existing duplicate behavior. Additional tests to affirm existing behavior are added for duplicate U extension attributes as well. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27775#issuecomment-3412979930 From naoto at openjdk.org Thu Oct 16 22:15:04 2025 From: naoto at openjdk.org (Naoto Sato) Date: Thu, 16 Oct 2025 22:15:04 GMT Subject: RFR: 8369590: LocaleEnhanceTest has incorrectly passing test case [v5] In-Reply-To: References: Message-ID: On Thu, 16 Oct 2025 21:56:33 GMT, Justin Lu wrote: >> This PR corrects _test/jdk/java/util/Locale/LocaleEnhanceTest.java_, which has two test cases under `testBuilderSetLanguageTag()` which accidentally pass. One checks that Locale.setLanguageTag(String) throws ILE for duplicate extensions and the other for duplicate U-extension keys. The test cases are updated to actually test the provided code. When the test cases are fixed, they now fail. >> >> Fixing the behavior to match the expectation of those test cases is consistent with the specification. >> >> From `Locale.forLanguageTag(String)`, >> >>> >>> *

If the specified language tag contains any ill-formed subtags, >>> * the first such subtag and all following subtags are ignored. Compare >>> * to {@link Locale.Builder#setLanguageTag(String)} which throws an exception >>> * in this case. >> >> and the RFC specification >> >>> Each singleton subtag MUST appear at most one time in each tag >>> (other than as a private use subtag). That is, singleton subtags >>> MUST NOT be repeated. For example, the tag "en-a-bbb-a-ccc" is >>> invalid because the subtag 'a' appears twice. >> >> Since duplicate extensions (and Unicode keys/attributes) are invalid, throwing `IllformedLocaleException` in (the strict) `Locale.Builder` and ignoring in (the lenient) `Locale.forLanguageTag` for such tags would be appropriate. This PR updates the implementation as such. > > Justin Lu has updated the pull request incrementally with one additional commit since the last revision: > > Remove impl changes. Simply update test to reflect duplicate ignoring behavior LGTM ------------- Marked as reviewed by naoto (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27775#pullrequestreview-3347175094 From pminborg at openjdk.org Fri Oct 17 09:25:01 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 09:25:01 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v12] 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: Update javadocs ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/a51f221a..6a6e804e Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=11 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=10-11 Stats: 59 lines in 1 file changed: 7 ins; 3 del; 49 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 Fri Oct 17 09:51:21 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 09:51:21 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v12] In-Reply-To: References: Message-ID: On Fri, 17 Oct 2025 09:25:01 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: > > Update javadocs src/java.base/share/classes/java/lang/LazyConstant.java line 46: > 44: * A lazy constant is created using the factory method > 45: * {@linkplain LazyConstant#of(Supplier) LazyConstant.of({@code })}. > 46: * When created, the contents (and hence the lazy constant itself) is not initialized. "When created, the lazy constant is not initialized, meaning it has no contents." E.g. it's the lazy constant that is initialized/not initialized. The content "just is". (or "is not", if not initialized). src/java.base/share/classes/java/lang/LazyConstant.java line 47: > 45: * {@linkplain LazyConstant#of(Supplier) LazyConstant.of({@code })}. > 46: * When created, the contents (and hence the lazy constant itself) is not initialized. > 47: * The contents (of type {@code T}) can then be initialized Again, "a lazy constant can be initialized, and its content retrieved, by calling get" src/java.base/share/classes/java/lang/LazyConstant.java line 50: > 48: * (and retrieved) by calling {@linkplain #get()}. The first time {@linkplain #get()} > 49: * is called, the underlying computing function (provided at construction) will > 50: * be invoked and the result will be used to initialize the contents. Once initialized, "and the result will be used to initialize the lazy constant. Once a lazy constant is initialized, its contents can never change..." ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439058429 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439060624 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439064085 From mcimadamore at openjdk.org Fri Oct 17 09:56:18 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 09:56:18 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v12] In-Reply-To: References: Message-ID: On Fri, 17 Oct 2025 09:25:01 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: > > Update javadocs src/java.base/share/classes/java/lang/LazyConstant.java line 54: > 52: * again upon subsequent {@linkplain #get() get} invocations. > 53: *

> 54: * A lazy constant is shallowly immutable, meaning the reference to the contents This para here seems a bit redundant. In part it repeats something already said (when initialized, contents will never change). I'd drop this from here, and maybe push it down to an API note (e.g. note: the contents of a lazy constant can be mutable -- e.g. an ArrayList). src/java.base/share/classes/java/lang/LazyConstant.java line 60: > 58: *

> 59: * Consider the following example where a lazy constant field "{@code logger}" is a > 60: * shallowly immutable holder of an object of type {@code Logger}: "where the lazy constant field "logger" holds an object of type Logger" src/java.base/share/classes/java/lang/LazyConstant.java line 77: > 75: *} > 76: *

> 77: * Initially, the lazy constant (and its contents) is not initialized. Suggestion: * Initially, the lazy constant is not initialized. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439072055 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439073774 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439075865 From mcimadamore at openjdk.org Fri Oct 17 10:08:22 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 10:08:22 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v12] In-Reply-To: References: Message-ID: On Fri, 17 Oct 2025 09:25:01 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: > > Update javadocs src/java.base/share/classes/java/lang/LazyConstant.java line 101: > 99: * {@linkplain Error}, that {@linkplain Throwable} is propagated to the caller, and the > 100: * lazy constant remains uninitialized. In other words, upon an unsuccessful invocation of > 101: * the computing function, neither a constant, the exception, nor the fact that "In other words" I don't think this sentence adds much. I think it's better to just drop it. The main thing to say is that if computing function is unsuccessful, the lazy constant stays uninitialized (which we already said). src/java.base/share/classes/java/lang/LazyConstant.java line 111: > 109: * which are held by lazy constants: > 110: * > 111: * {@snippet lang = java: If you wanted, you could reuse the `Component` class -- that one already has a lazy constant field, so if you put the component itself in another lazy constant field you have your composition example. src/java.base/share/classes/java/lang/LazyConstant.java line 144: > 142: * > 143: *

Thread Safety

> 144: * A lazy constant is guaranteed to be initialized atomically and at most once. If We already mention some of these above: "Furthermore, {@linkplain #get()} guarantees that, out of several threads trying to * invoke the computing function simultaneously, only one is ever selected for * computation" Maybe add a reference form that text to this section? src/java.base/share/classes/java/lang/LazyConstant.java line 152: > 150: *

> 151: * The invocation of the computing function and the resulting initialization of > 152: * the constant {@linkplain java.util.concurrent##MemoryVisibility happens-before} Do you mean constant or content? I think the latter? E.g. when you initialize a lazy constant, you safely publish its contents? (the lazy constant itself is already published) src/java.base/share/classes/java/lang/LazyConstant.java line 158: > 156: * Thread interruption does not cancel the initialization of a lazy constant. In other > 157: * words, if the computing thread is interrupted, {@code LazyConstant::get} doesn't clear > 158: * the interrupted thread?s status, nor does it throw an InterruptedException. Suggestion: * the interrupted thread?s status, nor does it throw an {@code InterruptedException}. src/java.base/share/classes/java/lang/LazyConstant.java line 164: > 162: * > 163: *

Performance

> 164: * A lazy constant can never change after it has been initialized. Therefore, The contents of a lazy constant can never change after the lazy constant has been initialized (again, spell out things clearly) src/java.base/share/classes/java/lang/LazyConstant.java line 166: > 164: * A lazy constant can never change after it has been initialized. Therefore, > 165: * a JVM implementation may, for an initialized lazy constant, elide all future reads > 166: * of that lazy constant and instead directly use any constant that it has previously "elide all future reads of that lazy constant's contents and instead use the contents that has been previously observed" ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439091644 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439096445 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439102301 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439110166 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439114804 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439119542 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439124386 From mcimadamore at openjdk.org Fri Oct 17 10:20:09 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 10:20:09 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v12] In-Reply-To: References: Message-ID: <2V6nUv7mUoPV7kx6uQXMTM9D4Xdm-1xEK7ErgbEAdds=.0bc05925-08b5-4799-903c-04b9bfa4760d@github.com> On Fri, 17 Oct 2025 09:25:01 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: > > Update javadocs src/java.base/share/classes/java/lang/LazyConstant.java line 168: > 166: * of that lazy constant and instead directly use any constant that it has previously > 167: * observed. We call this optimization constant folding. This is only possible if > 168: * the reference to the lazy constant is a VM constant (e.g. in cases where Not sure talking about VM constant is good. We could alternatively say: "if the lazy constant is stored in a static final field, either directly, or indirectly, via one or more trusted fields (i.e. any combination...)" src/java.base/share/classes/java/lang/LazyConstant.java line 179: > 177: * must be non-null, or a {@link NullPointerException} will be thrown. > 178: * > 179: * @apiNote Once a lazy constant is initialized with an object, the object cannot ever be Once a lazy constant is initialized, its contents can never be removed... src/java.base/share/classes/java/lang/LazyConstant.java line 182: > 180: * removed. This can be a source of an unintended memory leak. More specifically, > 181: * a lazy constant {@linkplain java.lang.ref##reachability strongly references} > 182: * the object it was initialized with. Hence, a lazy constant will hold s/the object it was initialized with/its contents (here and below) src/java.base/share/classes/java/lang/LazyConstant.java line 186: > 184: * is collected (if ever). > 185: *

> 186: * A {@code LazyConstant} that has a type parameter {@code T} that is an "A lazy constant whose contents is an array will not optimize access to the the elements of such array. Instead, ..." src/java.base/share/classes/java/lang/LazyConstant.java line 191: > 189: * Instead, a {@linkplain List#ofLazy(int, IntFunction) lazy list} of > 190: * arbitrary depth can be used, which provides constant components. > 191: * More generally, a lazy constant can hold other lazy constants of More generally... you said that in the composition section? src/java.base/share/classes/java/lang/LazyConstant.java line 233: > 231: > 232: /** > 233: * {@return the initialized contents. If not initialized, first computes and "initialized contents" is not a term you have defined in this javadoc. `get` returns the contents of this lazy constant. If the lazy constant is not initialized... src/java.base/share/classes/java/lang/LazyConstant.java line 267: > 265: */ > 266: @Override > 267: String toString(); I think it might be worth also defining a javadoc for equals/hashCode, to say explicitly that they will also not trigger initialization src/java.base/share/classes/java/lang/LazyConstant.java line 284: > 282: * directly. > 283: * > 284: * @param computingFunction in the form of a Supplier to be used to compute Suggestion: * @param computingFunction a {@code Supplier} used to initialize ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439138229 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439141653 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439144255 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439156012 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439150170 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439161143 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439169909 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439174349 From mcimadamore at openjdk.org Fri Oct 17 10:25:47 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 10:25:47 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v12] In-Reply-To: References: Message-ID: On Fri, 17 Oct 2025 09:25:01 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: > > Update javadocs src/java.base/share/classes/java/util/List.java line 1231: > 1229: * will be thrown. > 1230: *

> 1231: * The returned lazy list strongly references its computing We should say that hashCode/equals trigger computation src/java.base/share/classes/java/util/Map.java line 1784: > 1782: * will be thrown. > 1783: *

> 1784: * The returned lazy map strongly references its underlying Again, we should say that equals/hashCode triggers computation ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439200027 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439207782 From pminborg at openjdk.org Fri Oct 17 11:43:47 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 11:43:47 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v13] 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: Update wording on List/Map Object methods ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/6a6e804e..8cde6974 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=12 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=11-12 Stats: 12 lines in 2 files changed: 12 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 pminborg at openjdk.org Fri Oct 17 12:13:48 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 12:13:48 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v14] 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: Improve equals/hashCode document ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/8cde6974..77ae3fe1 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=13 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=12-13 Stats: 19 lines in 1 file changed: 16 ins; 0 del; 3 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 Fri Oct 17 12:28:15 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 12:28:15 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v15] 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: Improve method docs ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/77ae3fe1..e2c24f5c Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=14 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=13-14 Stats: 10 lines in 1 file changed: 1 ins; 0 del; 9 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 Fri Oct 17 13:13:45 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 13:13:45 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v16] 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: Update docs after comments ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/e2c24f5c..d961426d Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=15 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=14-15 Stats: 58 lines in 1 file changed: 3 ins; 16 del; 39 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 Fri Oct 17 14:06:44 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 14:06:44 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v17] 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: Revert the AbstractMap.keySet @Stable annotation ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/d961426d..698b4125 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=16 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=15-16 Stats: 5 lines in 2 files changed: 4 ins; 1 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 pminborg at openjdk.org Fri Oct 17 14:10:39 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 14:10:39 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v2] In-Reply-To: References: <90jKH5-Bb3vf27uhLPOUtgmYmZRFdH1voVYr8kIR__I=.2aff8cb2-38be-4dd3-a1df-e3f8a7a90542@github.com> Message-ID: On Thu, 16 Oct 2025 12:10:51 GMT, Per Minborg wrote: >> src/java.base/share/classes/java/util/AbstractMap.java line 335: >> >>> 333: */ >>> 334: @Stable >>> 335: transient Set keySet; >> >> Are?all?uses of?this?field in?`java.util` able?to?handle the?`@Stable`ness of?this?field correctly? > > That is a good question. The potentially different keySet values should be freely substitutable or else there seams to be something wrong. If they are FS, then the VM should be able to pick any. But it is a big assumption to say that *all* maps that extend AM behave in such a way. We could go back to the previous version and shadow the field. That seems safest. > > Note: there is work in progress to remove these fields. I've reverted the @Stable annotation on AM.keySet. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440164233 From mcimadamore at openjdk.org Fri Oct 17 14:17:54 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 14:17:54 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v16] In-Reply-To: References: Message-ID: <_kXdqyWalfyZNF_Bhnuw9NQh-9x3cutCQEB-r72fLR4=.aaadf47e-46d7-43d2-99dc-c6e0da1f8ad6@github.com> On Fri, 17 Oct 2025 13:13:45 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: > > Update docs after comments src/java.base/share/classes/java/lang/LazyConstant.java line 154: > 152: * > 153: *

Performance

> 154: * The contents of lazy constant can never change after it has been initialized. Therefore, Suggestion: * The contents of a lazy constant can never change after it has been initialized. Therefore, ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440185045 From mcimadamore at openjdk.org Fri Oct 17 14:30:06 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 14:30:06 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v16] In-Reply-To: References: Message-ID: On Fri, 17 Oct 2025 14:23:28 GMT, Maurizio Cimadamore wrote: >> Per Minborg has updated the pull request incrementally with one additional commit since the last revision: >> >> Update docs after comments > > src/java.base/share/classes/java/util/List.java line 1235: > >> 1233: * or more lazy elements. The returned list's {@linkplain Object#toString() toString()} >> 1234: * method never triggers initialization of elements. Instead, an >> 1235: * implementation-dependant string is returned for uninitialized elements. > > Suggestion: > > * implementation-dependent string is returned for uninitialized elements. Design comment: I note some internal discomfort at the fact that equals/hashCode trigger initialization, but toString does not... effectively this would make replacing a regular immutable list with a lazy list not possible in all cases. Not saying we should do anything now -- but something to monitor ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440214527 From mcimadamore at openjdk.org Fri Oct 17 14:30:05 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 14:30:05 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v16] In-Reply-To: References: Message-ID: On Fri, 17 Oct 2025 13:13:45 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: > > Update docs after comments src/java.base/share/classes/java/lang/LazyConstant.java line 157: > 155: * a JVM implementation may, for an initialized lazy constant, elide all future reads of > 156: * that lazy constant's contents and instead use the contents that has been previously > 157: * observed. We call this optimization constant folding. This is only possible This is still not ok. First, there seems to be some typo ("if the reference to the lazy constant in a static final field or..."). Secondly, trusted chain _to_ such field. I think it's the other way around, the trusted chain starts at a static final field, and then eventually gets to the lazy constant, possibly traversing one or more trusted fields. src/java.base/share/classes/java/lang/LazyConstant.java line 174: > 172: * the lazy constant itself is collected (if ever). > 173: *

> 174: * A lazy constant whose contents is an array will not optimize access to "While it's possible to store an array inside a lazy constant, doing so will not result in improved access to the array elements. Instead ..." src/java.base/share/classes/java/lang/LazyConstant.java line 289: > 287: * > 288: * @param computingFunction in the form of a {@linkplain Supplier} to be used > 289: * to compute the constant s/compute/initialize (e.g. the term "compute the constant" is not defined anywhere) src/java.base/share/classes/java/util/List.java line 1235: > 1233: * or more lazy elements. The returned list's {@linkplain Object#toString() toString()} > 1234: * method never triggers initialization of elements. Instead, an > 1235: * implementation-dependant string is returned for uninitialized elements. Suggestion: * implementation-dependent string is returned for uninitialized elements. src/java.base/share/classes/java/util/Map.java line 1788: > 1786: * or more lazy values. The returned maps's {@linkplain Object#toString() toString()} > 1787: * method never triggers initialization of values. Instead, an > 1788: * implementation-dependant string is returned for uninitialized values. Suggestion: * implementation-dependent string is returned for uninitialized values. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440193622 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440203445 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440207743 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440209019 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440216157 From pminborg at openjdk.org Fri Oct 17 14:29:55 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 14:29:55 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v18] 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 incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 104 additional commits since the last revision: - 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 - Fix test descriptions - Update first javadoc sentence - Rephrase docs on interrupt - ... and 94 more: https://git.openjdk.org/jdk/compare/e2f6db0f...fc064e47 ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/698b4125..fc064e47 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=17 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=16-17 Stats: 8176 lines in 211 files changed: 4888 ins; 2457 del; 831 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 Fri Oct 17 14:58:44 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 14:58:44 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v19] 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: Update after doc comments ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/fc064e47..6721ca4a Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=18 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=17-18 Stats: 14 lines in 3 files changed: 1 ins; 0 del; 13 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