hi, Chen Liang
    Thank you and OpenJDK community for accepting this suggestion.

Best regards,
vincent gao

Chen Liang <[email protected]> 于2025年12月16日周二 04:23写道:

> Hi Vincent,
> Thanks for the details. Our engineers have created a patch at
> https://github.com/openjdk/jdk/pull/28806.
> We seek to backport this to the 25 updates once this is merged. Ideally
> this would be part of update 25.0.3.
> Thank you again for this performance regression report!
>
> -Chen
> ------------------------------
> *From:* weigao <[email protected]>
> *Sent:* Thursday, December 11, 2025 8:12 PM
> *To:* Chen Liang <[email protected]>
> *Cc:* [email protected] <[email protected]>
> *Subject:* Re: [External] Feedback JDK-8318761 : Potential Issue in JDK
> 25 MessageFormat: Use of Internal Exception for Control Flow
>
>
> Hi , Chen Liang
> Thanks for the clarification.
> I agree this IllegalArgumentException is an internal exception used for
> control flow; it’s not printed externally by default.
> However, if it is thrown/caught frequently on a hot path, it can still
> incur a noticeable overhead (e.g., fillInStackTrace).
>
> We were able to notice this because our team monitors common JDK internal
> exceptions in our production workloads to validate whether changes in each
> release match our expectations.
> So even though this exception is not normally surfaced, we still observed
> the behavior.
>
> Below I’m adding a more concrete reproduction and benchmark data, for your
> evaluation of whether this is worth addressing/backporting in 25u.
>
> ## Reproducible benchmark (JMH) and results (JDK 21 vs JDK 25)
> I wrote a minimal JMH benchmark to simulate the cost of this pattern:
> ```
>
> private static final String CHOICE_PATTERN = "{0,choice,0#|1#{1}|2#{1} 
> ({2})}";
>
> @Param({"0", "1", "2"})
> public int choiceValue;
>
> private Object[] args;
>
> @Setup(Level.Iteration)
> public void setup() {
>     args = new Object[]{choiceValue, "us_en", "UTF-8"};
> }
>
> @Benchmark
> public void messageFormat_choice_static(Blackhole bh) {
>     String result = MessageFormat.format(CHOICE_PATTERN, args);
>     bh.consume(result);
> }
>
> ```
>
> Pattern: {0,choice,0#|1#{1}|2#{1} ({2})}
> Method: call MessageFormat.format(pattern, args) (creates a new
> MessageFormat instance and parses the pattern each time) to amplify
> parsing/branch costs; 1 thread; warmup 3x10s; measurement 5x10s; fork 1.
> Key results (Throughput, ops/ms):
>
> JDK 21.0.5: ~2379 to ~3204 ops/ms (depending on choiceValue = 0/1/2)
> JDK 25: ~866 to ~1029 ops/ms
>
> ```
>
> # JMH version: 1.37
> # VM version: JDK 21.0.5, OpenJDK 64-Bit Server VM, 21.0.5+11-LTS
>
> # Warmup: 3 iterations, 10 s each
> # Measurement: 5 iterations, 10 s each
> # Timeout: 10 min per iteration
> # Threads: 1 thread, will synchronize iterations
> # Benchmark mode: Throughput, ops/time
>
>
> Benchmark                                       (choiceValue)   Mode  Cnt     
> Score     Error   Units
> MessageFormatBench.messageFormat_choice_static              0  thrpt    5  
> 3204.770 ± 343.887  ops/ms
> MessageFormatBench.messageFormat_choice_static              1  thrpt    5  
> 2513.444 ± 380.943  ops/ms
> MessageFormatBench.messageFormat_choice_static              2  thrpt    5  
> 2379.665 ± 152.148  ops/ms
>
> ```
>
>
> ```
>
> # JMH version: 1.37
> # VM version: JDK 25, OpenJDK 64-Bit Server VM, 25+36-3489
>
>
> # Warmup: 3 iterations, 10 s each
> # Measurement: 5 iterations, 10 s each
> # Timeout: 10 min per iteration
> # Threads: 1 thread, will synchronize iterations
> # Benchmark mode: Throughput, ops/time
>
> Benchmark                                       (choiceValue)   Mode  Cnt     
> Score    Error   Units
> MessageFormatBench.messageFormat_choice_static              0  thrpt    5  
> 1029.018 ± 16.425  ops/ms
> MessageFormatBench.messageFormat_choice_static              1  thrpt    5   
> 932.762 ± 12.648  ops/ms
> MessageFormatBench.messageFormat_choice_static              2  thrpt    5   
> 866.487 ± 49.584  ops/ms
>
> ```
>
> This is roughly a 2.5x–3.1x throughput regression on JDK 25 compared to
> JDK 21.
>
> Note: the benchmark configuration is consistent between the two runs.
>
> Best regards,
> Vincent Gao
>
> Chen Liang <[email protected]> 于2025年12月12日周五 00:52写道:
>
> Hello Vincent Gao,
> I saw your Java Bugs submission. Unfortunately your stacktrace caused some
> confusion to our triage because it is an internal exception and that trace
> is never printed anywhere.
> Your suggestion is a reasonable enhancement, that we should not use ad-hoc
> exceptions for control flow, given they need to fill stack traces, which is
> extremely costly.
> Since this is a cleanup, we might commit this to mainline JDK first. If
> this proves to be a performance bottleneck on 25 updates, we can backport.
> Since you are writing here, I assume this has a non-negligible impact on
> performance.
> If you can share a flame graph showing the regression from this exception,
> or a benchmark difference between 21 and 25.0.1, this would be extremely
> helpful.
>
> Regards,
> Chen Liang
> ------------------------------
> *From:* core-libs-dev <[email protected]> on behalf of
> weigao <[email protected]>
> *Sent:* Wednesday, December 10, 2025 9:31 PM
> *To:* [email protected] <[email protected]>
> *Subject:* Re: [External] Feedback JDK-8318761 : Potential Issue in JDK
> 25 MessageFormat: Use of Internal Exception for Control Flow
>
> hi , because of ``private static FormatStyle fromString(String text)`
> throw exception and the try catch exception just set the deault value `
> FormatStyle.SUBFORMATPATTERN`  , so why just make this function retuen
> this value like ? Is it better , right  ?
> ```
>
> private static FormatStyle fromString(String text) {
>     for (FormatStyle style : values()) {
>         // Also check trimmed case-insensitive for historical reasons
>         if (style != FormatStyle.SUBFORMATPATTERN &&
>                 text.trim().compareToIgnoreCase(style.text) == 0) {
>             return style;
>         }
>     }
>     return FormatStyle.SUBFORMATPATTERN;
> }
>
> ```
>
> weigao <[email protected]> 于2025年12月11日周四 11:21写道:
>
> Hello,
>
> I would like to report a potential design issue in the JDK 25
> implementation of MessageFormat.
>
> While working with java.util.Locale#getDisplayName(), I found that JDK
> internals throw and catch an IllegalArgumentException due to the
> following pattern added in the resource bundles:
>
>    -
>
>    sun.util.resources.cldr.LocaleNames
>    -
>
>    sun.util.resources.LocaleNames
>
> The pattern in question is:
>
> DisplayNamePattern: {0,choice,0#|1#{1}|2#{1} ({2})}
>
> This change originates from the following commit:
> adoptium/jdk@00ffc42 — which adds a pattern for MessageFormat.
> However, choice is *not* a valid type for FormatStyle.
>
> As a result, calling Locale#getDisplayName() triggers the following
> exception inside JDK code:
>
> java.lang.IllegalArgumentException
>     at 
> java.base/java.text.MessageFormat$FormatStyle.fromString(MessageFormat.java:2013)
>     at 
> java.base/java.text.MessageFormat.formatFromPattern(MessageFormat.java:1718)
>     at 
> java.base/java.text.MessageFormat.setFormatFromPattern(MessageFormat.java:1679)
>     at 
> java.base/java.text.MessageFormat.applyPatternImpl(MessageFormat.java:660)
>     at java.base/java.text.MessageFormat.<init>(MessageFormat.java:516)
>     at java.base/java.util.Locale.getDisplayName(Locale.java:2309)
>
> The implementation currently relies on exception-based logic:
>
> try {
>     fStyle = FormatStyle.fromString(style);
> } catch (IllegalArgumentException iae) {
>     fStyle = FormatStyle.SUBFORMATPATTERN;
> }
>
> I understand that MessageFormat catches this exception and falls back to
> SUBFORMATPATTERN, but using exceptions to control expected logic paths
> may not be ideal—especially since FormatStyle.fromString() is only used
> by MessageFormat.
>
> A potentially cleaner approach could be to have FormatStyle.fromString()
> return FormatStyle.SUBFORMATPATTERN directly when encountering unknown
> style identifiers, instead of throwing an exception.
>
> *JDK Version Observed:*
>
> OpenJDK Runtime Environment Temurin-25.0.1+8 (build 25.0.1+8-LTS)
>
> Please let me know if this behavior is intentional, or if it should be
> considered for improvement.
>
> Best regards,
> vincent gao
>
>

Reply via email to