mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8331932: Startup regressions in 23-b13
Reviewed-by: alanb, naoto, liach
This commit is contained in:
parent
7db6a3f0ee
commit
d654124502
4 changed files with 56 additions and 16 deletions
|
@ -48,6 +48,7 @@ import java.io.Serializable;
|
|||
import java.text.DateFormat;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.spi.LocaleNameProvider;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
@ -980,29 +981,36 @@ public final class Locale implements Cloneable, Serializable {
|
|||
return getInstance(baseloc, extensions);
|
||||
}
|
||||
|
||||
|
||||
static Locale getInstance(BaseLocale baseloc, LocaleExtensions extensions) {
|
||||
if (extensions == null) {
|
||||
Locale locale = CONSTANT_LOCALES.get(baseloc);
|
||||
if (locale != null) {
|
||||
return locale;
|
||||
}
|
||||
return LOCALE_CACHE.computeIfAbsent(baseloc, Locale::createLocale);
|
||||
return LOCALE_CACHE.computeIfAbsent(baseloc, LOCALE_CREATOR);
|
||||
} else {
|
||||
LocaleKey key = new LocaleKey(baseloc, extensions);
|
||||
return LOCALE_CACHE.computeIfAbsent(key, Locale::createLocale);
|
||||
return LOCALE_CACHE.computeIfAbsent(key, LOCALE_CREATOR);
|
||||
}
|
||||
}
|
||||
|
||||
private static final ReferencedKeyMap<Object, Locale> LOCALE_CACHE = ReferencedKeyMap.create(true, ConcurrentHashMap::new);
|
||||
private static Locale createLocale(Object key) {
|
||||
if (key instanceof BaseLocale base) {
|
||||
return new Locale(base, null);
|
||||
private static final ReferencedKeyMap<Object, Locale> LOCALE_CACHE
|
||||
= ReferencedKeyMap.create(true, ReferencedKeyMap.concurrentHashMapSupplier());
|
||||
|
||||
private static final Function<Object, Locale> LOCALE_CREATOR = new Function<>() {
|
||||
@Override
|
||||
public Locale apply(Object key) {
|
||||
if (key instanceof BaseLocale base) {
|
||||
return new Locale(base, null);
|
||||
}
|
||||
LocaleKey lk = (LocaleKey)key;
|
||||
return new Locale(lk.base, lk.exts);
|
||||
}
|
||||
LocaleKey lk = (LocaleKey)key;
|
||||
return new Locale(lk.base, lk.exts);
|
||||
}
|
||||
};
|
||||
|
||||
private static final class LocaleKey {
|
||||
|
||||
private final BaseLocale base;
|
||||
private final LocaleExtensions exts;
|
||||
private final int hash;
|
||||
|
|
|
@ -99,6 +99,21 @@ public final class ReferencedKeyMap<K, V> implements Map<K, V> {
|
|||
*/
|
||||
private final ReferenceQueue<K> stale;
|
||||
|
||||
/**
|
||||
* @return a supplier to create a {@code ConcurrentHashMap} appropriate for use in the
|
||||
* create methods.
|
||||
* @param <K> the type of keys maintained by the new map
|
||||
* @param <V> the type of mapped values
|
||||
*/
|
||||
public static <K, V> Supplier<Map<ReferenceKey<K>, V>> concurrentHashMapSupplier() {
|
||||
return new Supplier<>() {
|
||||
@Override
|
||||
public Map<ReferenceKey<K>, V> get() {
|
||||
return new ConcurrentHashMap<>();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor.
|
||||
*
|
||||
|
|
|
@ -75,6 +75,15 @@ public final class ReferencedKeySet<T> extends AbstractSet<T> {
|
|||
*/
|
||||
final ReferencedKeyMap<T, ReferenceKey<T>> map;
|
||||
|
||||
/**
|
||||
* @return a supplier to create a {@code ConcurrentHashMap} appropriate for use in the
|
||||
* create methods.
|
||||
* @param <E> the type of elements maintained by this set
|
||||
*/
|
||||
public static <E> Supplier<Map<ReferenceKey<E>, ReferenceKey<E>>> concurrentHashMapSupplier() {
|
||||
return ReferencedKeyMap.concurrentHashMapSupplier();
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor.
|
||||
*
|
||||
|
|
|
@ -38,7 +38,7 @@ import jdk.internal.util.StaticProperty;
|
|||
import jdk.internal.vm.annotation.Stable;
|
||||
|
||||
import java.util.StringJoiner;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public final class BaseLocale {
|
||||
|
||||
|
@ -93,7 +93,7 @@ public final class BaseLocale {
|
|||
|
||||
// Interned BaseLocale cache
|
||||
private static final ReferencedKeySet<BaseLocale> CACHE =
|
||||
ReferencedKeySet.create(true, ConcurrentHashMap::new);
|
||||
ReferencedKeySet.create(true, ReferencedKeySet.concurrentHashMapSupplier());
|
||||
|
||||
public static final String SEP = "_";
|
||||
|
||||
|
@ -164,13 +164,21 @@ public final class BaseLocale {
|
|||
// "interned" instance can subsequently be used by the Locale
|
||||
// instance which guarantees the locale components are properly cased/interned.
|
||||
return CACHE.intern(new BaseLocale(language, script, region, variant),
|
||||
(b) -> new BaseLocale(
|
||||
LocaleUtils.toLowerString(b.language).intern(),
|
||||
LocaleUtils.toTitleString(b.script).intern(),
|
||||
LocaleUtils.toUpperString(b.region).intern(),
|
||||
b.variant.intern()));
|
||||
// Avoid lambdas since this may be on the bootstrap path in many locales
|
||||
INTERNER);
|
||||
}
|
||||
|
||||
public static final UnaryOperator<BaseLocale> INTERNER = new UnaryOperator<>() {
|
||||
@Override
|
||||
public BaseLocale apply(BaseLocale b) {
|
||||
return new BaseLocale(
|
||||
LocaleUtils.toLowerString(b.language).intern(),
|
||||
LocaleUtils.toTitleString(b.script).intern(),
|
||||
LocaleUtils.toUpperString(b.region).intern(),
|
||||
b.variant.intern());
|
||||
}
|
||||
};
|
||||
|
||||
public static String convertOldISOCodes(String language) {
|
||||
return switch (language) {
|
||||
case "he", "iw" -> OLD_ISO_CODES ? "iw" : "he";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue