Skip to content

Commit 52338c9

Browse files
committed
8358520: Improve lazy computation in BreakIteratorResourceBundle and related classes
Reviewed-by: naoto, jlu
1 parent 91f1260 commit 52338c9

File tree

3 files changed

+65
-87
lines changed

3 files changed

+65
-87
lines changed

src/java.base/share/classes/java/util/ResourceBundle.java

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import java.net.URLConnection;
5555
import java.util.concurrent.ConcurrentHashMap;
5656
import java.util.concurrent.ConcurrentMap;
57+
import java.util.function.Supplier;
5758
import java.util.jar.JarEntry;
5859
import java.util.spi.ResourceBundleControlProvider;
5960
import java.util.spi.ResourceBundleProvider;
@@ -487,7 +488,20 @@ public String getBaseBundleName() {
487488
/**
488489
* A Set of the keys contained only in this ResourceBundle.
489490
*/
490-
private volatile Set<String> keySet;
491+
private final Supplier<Set<String>> keySet = StableValue.supplier(
492+
new Supplier<>() { public Set<String> get() { return keySet0(); }});
493+
494+
private Set<String> keySet0() {
495+
final Set<String> keys = new HashSet<>();
496+
final Enumeration<String> enumKeys = getKeys();
497+
while (enumKeys.hasMoreElements()) {
498+
final String key = enumKeys.nextElement();
499+
if (handleGetObject(key) != null) {
500+
keys.add(key);
501+
}
502+
}
503+
return keys;
504+
}
491505

492506
/**
493507
* Sole constructor. (For invocation by subclass constructors, typically
@@ -2298,22 +2312,7 @@ public Set<String> keySet() {
22982312
* @since 1.6
22992313
*/
23002314
protected Set<String> handleKeySet() {
2301-
if (keySet == null) {
2302-
synchronized (this) {
2303-
if (keySet == null) {
2304-
Set<String> keys = new HashSet<>();
2305-
Enumeration<String> enumKeys = getKeys();
2306-
while (enumKeys.hasMoreElements()) {
2307-
String key = enumKeys.nextElement();
2308-
if (handleGetObject(key) != null) {
2309-
keys.add(key);
2310-
}
2311-
}
2312-
keySet = keys;
2313-
}
2314-
}
2315-
}
2316-
return keySet;
2315+
return keySet.get();
23172316
}
23182317

23192318

src/java.base/share/classes/sun/util/resources/BreakIteratorResourceBundle.java

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
3030
import java.util.Enumeration;
3131
import java.util.ResourceBundle;
3232
import java.util.Set;
33+
import java.util.function.Supplier;
3334

3435
/**
3536
* BreakIteratorResourceBundle is an abstract class for loading BreakIterator
@@ -49,7 +50,15 @@ public abstract class BreakIteratorResourceBundle extends ResourceBundle {
4950
// those keys must be added to NON_DATA_KEYS.
5051
private static final Set<String> NON_DATA_KEYS = Set.of("BreakIteratorClasses");
5152

52-
private volatile Set<String> keys;
53+
private final Supplier<Set<String>> keys = StableValue.supplier(
54+
new Supplier<>() { public Set<String> get() { return keys0(); }});
55+
56+
private Set<String> keys0() {
57+
final ResourceBundle info = getBreakIteratorInfo();
58+
final Set<String> k = info.keySet();
59+
k.removeAll(NON_DATA_KEYS);
60+
return k;
61+
}
5362

5463
/**
5564
* Returns an instance of the corresponding {@code BreakIteratorInfo} (basename).
@@ -84,16 +93,6 @@ public Enumeration<String> getKeys() {
8493

8594
@Override
8695
protected Set<String> handleKeySet() {
87-
if (keys == null) {
88-
ResourceBundle info = getBreakIteratorInfo();
89-
Set<String> k = info.keySet();
90-
k.removeAll(NON_DATA_KEYS);
91-
synchronized (this) {
92-
if (keys == null) {
93-
keys = k;
94-
}
95-
}
96-
}
97-
return keys;
96+
return keys.get();
9897
}
9998
}

src/java.base/share/classes/sun/util/resources/OpenListResourceBundle.java

Lines changed: 37 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -44,8 +44,11 @@
4444
import java.util.HashMap;
4545
import java.util.HashSet;
4646
import java.util.Map;
47+
import java.util.Objects;
4748
import java.util.ResourceBundle;
4849
import java.util.Set;
50+
import java.util.function.Supplier;
51+
4952
import sun.util.ResourceBundleEnumeration;
5053

5154
/**
@@ -69,12 +72,9 @@ protected OpenListResourceBundle() {
6972
// Implements java.util.ResourceBundle.handleGetObject; inherits javadoc specification.
7073
@Override
7174
protected Object handleGetObject(String key) {
72-
if (key == null) {
73-
throw new NullPointerException();
74-
}
75-
76-
loadLookupTablesIfNecessary();
77-
return lookup.get(key); // this class ignores locales
75+
Objects.requireNonNull(key);
76+
return lookup.get()
77+
.get(key); // this class ignores locales
7878
}
7979

8080
/**
@@ -93,65 +93,20 @@ public Enumeration<String> getKeys() {
9393
*/
9494
@Override
9595
protected Set<String> handleKeySet() {
96-
loadLookupTablesIfNecessary();
97-
return lookup.keySet();
96+
return lookup.get()
97+
.keySet();
9898
}
9999

100100
@Override
101101
public Set<String> keySet() {
102-
if (keyset != null) {
103-
return keyset;
104-
}
105-
Set<String> ks = createSet();
106-
ks.addAll(handleKeySet());
107-
if (parent != null) {
108-
ks.addAll(parent.keySet());
109-
}
110-
synchronized (this) {
111-
if (keyset == null) {
112-
keyset = ks;
113-
}
114-
}
115-
return keyset;
102+
return keyset.get();
116103
}
117104

118105
/**
119106
* See ListResourceBundle class description.
120107
*/
121108
protected abstract Object[][] getContents();
122109

123-
/**
124-
* Load lookup tables if they haven't been loaded already.
125-
*/
126-
void loadLookupTablesIfNecessary() {
127-
if (lookup == null) {
128-
loadLookup();
129-
}
130-
}
131-
132-
/**
133-
* We lazily load the lookup hashtable. This function does the
134-
* loading.
135-
*/
136-
private void loadLookup() {
137-
Object[][] contents = getContents();
138-
Map<String, Object> temp = createMap(contents.length);
139-
for (int i = 0; i < contents.length; ++i) {
140-
// key must be non-null String, value must be non-null
141-
String key = (String) contents[i][0];
142-
Object value = contents[i][1];
143-
if (key == null || value == null) {
144-
throw new NullPointerException();
145-
}
146-
temp.put(key, value);
147-
}
148-
synchronized (this) {
149-
if (lookup == null) {
150-
lookup = temp;
151-
}
152-
}
153-
}
154-
155110
/**
156111
* Lets subclasses provide specialized Map implementations.
157112
* Default uses HashMap.
@@ -164,6 +119,31 @@ protected <E> Set<E> createSet() {
164119
return new HashSet<>();
165120
}
166121

167-
private volatile Map<String, Object> lookup;
168-
private volatile Set<String> keyset;
122+
private final Supplier<Map<String, Object>> lookup = StableValue.supplier(
123+
new Supplier<>() { public Map<String, Object> get() { return lookup0(); }});
124+
125+
private Map<String, Object> lookup0() {
126+
final Object[][] contents = getContents();
127+
final Map<String, Object> temp = createMap(contents.length);
128+
for (Object[] content : contents) {
129+
// key must be non-null String, value must be non-null
130+
final String key = Objects.requireNonNull((String) content[0]);
131+
final Object value = Objects.requireNonNull(content[1]);
132+
temp.put(key, value);
133+
}
134+
return temp;
135+
}
136+
137+
private final Supplier<Set<String>> keyset = StableValue.supplier(
138+
new Supplier<>() { public Set<String> get() { return keyset0(); }});
139+
140+
private Set<String> keyset0() {
141+
final Set<String> ks = createSet();
142+
ks.addAll(handleKeySet());
143+
if (parent != null) {
144+
ks.addAll(parent.keySet());
145+
}
146+
return ks;
147+
}
148+
169149
}

0 commit comments

Comments
 (0)