8358520: Improve lazy computation in BreakIteratorResourceBundle and related classes
Reviewed-by: naoto, jlu
This commit is contained in:
parent
91f12600d2
commit
52338c94f6
@ -54,6 +54,7 @@ import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.spi.ResourceBundleControlProvider;
|
||||
import java.util.spi.ResourceBundleProvider;
|
||||
@ -487,7 +488,20 @@ public abstract class ResourceBundle {
|
||||
/**
|
||||
* A Set of the keys contained only in this ResourceBundle.
|
||||
*/
|
||||
private volatile Set<String> keySet;
|
||||
private final Supplier<Set<String>> keySet = StableValue.supplier(
|
||||
new Supplier<>() { public Set<String> get() { return keySet0(); }});
|
||||
|
||||
private Set<String> keySet0() {
|
||||
final Set<String> keys = new HashSet<>();
|
||||
final Enumeration<String> enumKeys = getKeys();
|
||||
while (enumKeys.hasMoreElements()) {
|
||||
final String key = enumKeys.nextElement();
|
||||
if (handleGetObject(key) != null) {
|
||||
keys.add(key);
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sole constructor. (For invocation by subclass constructors, typically
|
||||
@ -2298,22 +2312,7 @@ public abstract class ResourceBundle {
|
||||
* @since 1.6
|
||||
*/
|
||||
protected Set<String> handleKeySet() {
|
||||
if (keySet == null) {
|
||||
synchronized (this) {
|
||||
if (keySet == null) {
|
||||
Set<String> keys = new HashSet<>();
|
||||
Enumeration<String> enumKeys = getKeys();
|
||||
while (enumKeys.hasMoreElements()) {
|
||||
String key = enumKeys.nextElement();
|
||||
if (handleGetObject(key) != null) {
|
||||
keys.add(key);
|
||||
}
|
||||
}
|
||||
keySet = keys;
|
||||
}
|
||||
}
|
||||
}
|
||||
return keySet;
|
||||
return keySet.get();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,6 +30,7 @@ import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* BreakIteratorResourceBundle is an abstract class for loading BreakIterator
|
||||
@ -49,7 +50,15 @@ public abstract class BreakIteratorResourceBundle extends ResourceBundle {
|
||||
// those keys must be added to NON_DATA_KEYS.
|
||||
private static final Set<String> NON_DATA_KEYS = Set.of("BreakIteratorClasses");
|
||||
|
||||
private volatile Set<String> keys;
|
||||
private final Supplier<Set<String>> keys = StableValue.supplier(
|
||||
new Supplier<>() { public Set<String> get() { return keys0(); }});
|
||||
|
||||
private Set<String> keys0() {
|
||||
final ResourceBundle info = getBreakIteratorInfo();
|
||||
final Set<String> k = info.keySet();
|
||||
k.removeAll(NON_DATA_KEYS);
|
||||
return k;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of the corresponding {@code BreakIteratorInfo} (basename).
|
||||
@ -84,16 +93,6 @@ public abstract class BreakIteratorResourceBundle extends ResourceBundle {
|
||||
|
||||
@Override
|
||||
protected Set<String> handleKeySet() {
|
||||
if (keys == null) {
|
||||
ResourceBundle info = getBreakIteratorInfo();
|
||||
Set<String> k = info.keySet();
|
||||
k.removeAll(NON_DATA_KEYS);
|
||||
synchronized (this) {
|
||||
if (keys == null) {
|
||||
keys = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
return keys.get();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -44,8 +44,11 @@ import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import sun.util.ResourceBundleEnumeration;
|
||||
|
||||
/**
|
||||
@ -69,12 +72,9 @@ public abstract class OpenListResourceBundle extends ResourceBundle {
|
||||
// Implements java.util.ResourceBundle.handleGetObject; inherits javadoc specification.
|
||||
@Override
|
||||
protected Object handleGetObject(String key) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
loadLookupTablesIfNecessary();
|
||||
return lookup.get(key); // this class ignores locales
|
||||
Objects.requireNonNull(key);
|
||||
return lookup.get()
|
||||
.get(key); // this class ignores locales
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,26 +93,13 @@ public abstract class OpenListResourceBundle extends ResourceBundle {
|
||||
*/
|
||||
@Override
|
||||
protected Set<String> handleKeySet() {
|
||||
loadLookupTablesIfNecessary();
|
||||
return lookup.keySet();
|
||||
return lookup.get()
|
||||
.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> keySet() {
|
||||
if (keyset != null) {
|
||||
return keyset;
|
||||
}
|
||||
Set<String> ks = createSet();
|
||||
ks.addAll(handleKeySet());
|
||||
if (parent != null) {
|
||||
ks.addAll(parent.keySet());
|
||||
}
|
||||
synchronized (this) {
|
||||
if (keyset == null) {
|
||||
keyset = ks;
|
||||
}
|
||||
}
|
||||
return keyset;
|
||||
return keyset.get();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -120,38 +107,6 @@ public abstract class OpenListResourceBundle extends ResourceBundle {
|
||||
*/
|
||||
protected abstract Object[][] getContents();
|
||||
|
||||
/**
|
||||
* Load lookup tables if they haven't been loaded already.
|
||||
*/
|
||||
void loadLookupTablesIfNecessary() {
|
||||
if (lookup == null) {
|
||||
loadLookup();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We lazily load the lookup hashtable. This function does the
|
||||
* loading.
|
||||
*/
|
||||
private void loadLookup() {
|
||||
Object[][] contents = getContents();
|
||||
Map<String, Object> temp = createMap(contents.length);
|
||||
for (int i = 0; i < contents.length; ++i) {
|
||||
// key must be non-null String, value must be non-null
|
||||
String key = (String) contents[i][0];
|
||||
Object value = contents[i][1];
|
||||
if (key == null || value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
temp.put(key, value);
|
||||
}
|
||||
synchronized (this) {
|
||||
if (lookup == null) {
|
||||
lookup = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets subclasses provide specialized Map implementations.
|
||||
* Default uses HashMap.
|
||||
@ -164,6 +119,31 @@ public abstract class OpenListResourceBundle extends ResourceBundle {
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
private volatile Map<String, Object> lookup;
|
||||
private volatile Set<String> keyset;
|
||||
private final Supplier<Map<String, Object>> lookup = StableValue.supplier(
|
||||
new Supplier<>() { public Map<String, Object> get() { return lookup0(); }});
|
||||
|
||||
private Map<String, Object> lookup0() {
|
||||
final Object[][] contents = getContents();
|
||||
final Map<String, Object> temp = createMap(contents.length);
|
||||
for (Object[] content : contents) {
|
||||
// key must be non-null String, value must be non-null
|
||||
final String key = Objects.requireNonNull((String) content[0]);
|
||||
final Object value = Objects.requireNonNull(content[1]);
|
||||
temp.put(key, value);
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
private final Supplier<Set<String>> keyset = StableValue.supplier(
|
||||
new Supplier<>() { public Set<String> get() { return keyset0(); }});
|
||||
|
||||
private Set<String> keyset0() {
|
||||
final Set<String> ks = createSet();
|
||||
ks.addAll(handleKeySet());
|
||||
if (parent != null) {
|
||||
ks.addAll(parent.keySet());
|
||||
}
|
||||
return ks;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user