From f364fcab792ed5a14e5c2779fa85ecc9d6915ae3 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Mon, 18 Aug 2025 05:32:03 +0000 Subject: [PATCH] 8359119: Change Charset to use StableValue Reviewed-by: alanb, rriggs --- .../classes/java/nio/charset/Charset.java | 116 +++++++++--------- 1 file changed, 56 insertions(+), 60 deletions(-) diff --git a/src/java.base/share/classes/java/nio/charset/Charset.java b/src/java.base/share/classes/java/nio/charset/Charset.java index b36e11cdc36..1eb3c9c2094 100644 --- a/src/java.base/share/classes/java/nio/charset/Charset.java +++ b/src/java.base/share/classes/java/nio/charset/Charset.java @@ -37,13 +37,16 @@ import java.nio.charset.spi.CharsetProvider; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Objects; import java.util.ServiceLoader; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; +import java.util.function.Supplier; /** @@ -381,17 +384,7 @@ public abstract class Charset }; } - private static class ThreadTrackHolder { - static final ThreadTracker TRACKER = new ThreadTracker(); - } - - private static Object tryBeginLookup() { - return ThreadTrackHolder.TRACKER.tryBegin(); - } - - private static void endLookup(Object key) { - ThreadTrackHolder.TRACKER.end(key); - } + private static final ScopedValue IN_LOOKUP = ScopedValue.newInstance(); private static Charset lookupViaProviders(final String charsetName) { @@ -406,48 +399,54 @@ public abstract class Charset if (!VM.isBooted()) return null; - Object key = tryBeginLookup(); - if (key == null) { + if (IN_LOOKUP.isBound()) { // Avoid recursive provider lookups return null; } try { - for (Iterator i = providers(); i.hasNext();) { - CharsetProvider cp = i.next(); - Charset cs = cp.charsetForName(charsetName); - if (cs != null) - return cs; - } - return null; - } finally { - endLookup(key); + return ScopedValue.where(IN_LOOKUP, true).call( + new ScopedValue.CallableOp() { + @Override + public Charset call() { + for (Iterator i = providers(); i.hasNext(); ) { + CharsetProvider cp = i.next(); + Charset cs = cp.charsetForName(charsetName); + if (cs != null) + return cs; + } + return null; + } + } + ); + } catch (Exception t) { + // Should not happen + throw new RuntimeException(t); } + } /* The extended set of charsets */ - private static class ExtendedProviderHolder { - static final CharsetProvider[] extendedProviders = extendedProviders(); - // returns ExtendedProvider, if installed - private static CharsetProvider[] extendedProviders() { - CharsetProvider[] cps = new CharsetProvider[1]; - int n = 0; - ServiceLoader sl = + private static final Supplier> EXTENDED_PROVIDERS = StableValue.supplier( + new Supplier<>() { public List get() { return extendedProviders0(); }}); + + private static List extendedProviders0() { + CharsetProvider[] cps = new CharsetProvider[1]; + int n = 0; + final ServiceLoader sl = ServiceLoader.loadInstalled(CharsetProvider.class); - for (CharsetProvider cp : sl) { - if (n + 1 > cps.length) { - cps = Arrays.copyOf(cps, cps.length << 1); - } - cps[n++] = cp; + for (CharsetProvider cp : sl) { + if (n + 1 > cps.length) { + cps = Arrays.copyOf(cps, cps.length << 1); } - return n == cps.length ? cps : Arrays.copyOf(cps, n); + cps[n++] = cp; } + return List.of(n == cps.length ? cps : Arrays.copyOf(cps, n)); } private static Charset lookupExtendedCharset(String charsetName) { if (!VM.isBooted()) // see lookupViaProviders() return null; - CharsetProvider[] ecps = ExtendedProviderHolder.extendedProviders; - for (CharsetProvider cp : ecps) { + for (CharsetProvider cp : EXTENDED_PROVIDERS.get()) { Charset cs = cp.charsetForName(charsetName); if (cs != null) return cs; @@ -608,8 +607,7 @@ public abstract class Charset new TreeMap<>( String.CASE_INSENSITIVE_ORDER); put(standardProvider.charsets(), m); - CharsetProvider[] ecps = ExtendedProviderHolder.extendedProviders; - for (CharsetProvider ecp :ecps) { + for (CharsetProvider ecp : EXTENDED_PROVIDERS.get()) { put(ecp.charsets(), m); } for (Iterator i = providers(); i.hasNext();) { @@ -619,7 +617,16 @@ public abstract class Charset return Collections.unmodifiableSortedMap(m); } - private @Stable static Charset defaultCharset; + private static final Supplier defaultCharset = StableValue.supplier( + new Supplier<>() { public Charset get() { return defaultCharset0(); }}); + + private static Charset defaultCharset0() { + // do not look for providers other than the standard one + final Charset cs = standardProvider.charsetForName(StaticProperty.fileEncoding()); + return (cs == null) + ? sun.nio.cs.UTF_8.INSTANCE + : cs; + } /** * Returns the default charset of this Java virtual machine. @@ -640,25 +647,19 @@ public abstract class Charset * @since 1.5 */ public static Charset defaultCharset() { - if (defaultCharset == null) { - synchronized (Charset.class) { - // do not look for providers other than the standard one - Charset cs = standardProvider.charsetForName(StaticProperty.fileEncoding()); - if (cs != null) - defaultCharset = cs; - else - defaultCharset = sun.nio.cs.UTF_8.INSTANCE; - } - } - return defaultCharset; + return defaultCharset.get(); } /* -- Instance fields and methods -- */ - private final String name; // tickles a bug in oldjavac - private final String[] aliases; // tickles a bug in oldjavac - private Set aliasSet; + @Stable + private final String name; + @Stable + private final String[] aliases; + @Stable + private final Supplier> aliasSet = StableValue.supplier( + new Supplier<>() { public Set get() { return Set.of(aliases); }}); /** * Initializes a new charset with the given canonical name and alias @@ -710,12 +711,7 @@ public abstract class Charset * @return An immutable set of this charset's aliases */ public final Set aliases() { - Set set = this.aliasSet; - if (set == null) { - set = Set.of(aliases); - this.aliasSet = set; - } - return set; + return aliasSet.get(); } /**