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.net.URLConnection;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.spi.ResourceBundleControlProvider;
|
import java.util.spi.ResourceBundleControlProvider;
|
||||||
import java.util.spi.ResourceBundleProvider;
|
import java.util.spi.ResourceBundleProvider;
|
||||||
@ -487,7 +488,20 @@ public abstract class ResourceBundle {
|
|||||||
/**
|
/**
|
||||||
* A Set of the keys contained only in this 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
|
* Sole constructor. (For invocation by subclass constructors, typically
|
||||||
@ -2298,22 +2312,7 @@ public abstract class ResourceBundle {
|
|||||||
* @since 1.6
|
* @since 1.6
|
||||||
*/
|
*/
|
||||||
protected Set<String> handleKeySet() {
|
protected Set<String> handleKeySet() {
|
||||||
if (keySet == null) {
|
return keySet.get();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.Enumeration;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BreakIteratorResourceBundle is an abstract class for loading BreakIterator
|
* 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.
|
// those keys must be added to NON_DATA_KEYS.
|
||||||
private static final Set<String> NON_DATA_KEYS = Set.of("BreakIteratorClasses");
|
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).
|
* Returns an instance of the corresponding {@code BreakIteratorInfo} (basename).
|
||||||
@ -84,16 +93,6 @@ public abstract class BreakIteratorResourceBundle extends ResourceBundle {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<String> handleKeySet() {
|
protected Set<String> handleKeySet() {
|
||||||
if (keys == null) {
|
return keys.get();
|
||||||
ResourceBundle info = getBreakIteratorInfo();
|
|
||||||
Set<String> k = info.keySet();
|
|
||||||
k.removeAll(NON_DATA_KEYS);
|
|
||||||
synchronized (this) {
|
|
||||||
if (keys == null) {
|
|
||||||
keys = k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import sun.util.ResourceBundleEnumeration;
|
import sun.util.ResourceBundleEnumeration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,12 +72,9 @@ public abstract class OpenListResourceBundle extends ResourceBundle {
|
|||||||
// Implements java.util.ResourceBundle.handleGetObject; inherits javadoc specification.
|
// Implements java.util.ResourceBundle.handleGetObject; inherits javadoc specification.
|
||||||
@Override
|
@Override
|
||||||
protected Object handleGetObject(String key) {
|
protected Object handleGetObject(String key) {
|
||||||
if (key == null) {
|
Objects.requireNonNull(key);
|
||||||
throw new NullPointerException();
|
return lookup.get()
|
||||||
}
|
.get(key); // this class ignores locales
|
||||||
|
|
||||||
loadLookupTablesIfNecessary();
|
|
||||||
return lookup.get(key); // this class ignores locales
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,26 +93,13 @@ public abstract class OpenListResourceBundle extends ResourceBundle {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Set<String> handleKeySet() {
|
protected Set<String> handleKeySet() {
|
||||||
loadLookupTablesIfNecessary();
|
return lookup.get()
|
||||||
return lookup.keySet();
|
.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> keySet() {
|
public Set<String> keySet() {
|
||||||
if (keyset != null) {
|
return keyset.get();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -120,38 +107,6 @@ public abstract class OpenListResourceBundle extends ResourceBundle {
|
|||||||
*/
|
*/
|
||||||
protected abstract Object[][] getContents();
|
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.
|
* Lets subclasses provide specialized Map implementations.
|
||||||
* Default uses HashMap.
|
* Default uses HashMap.
|
||||||
@ -164,6 +119,31 @@ public abstract class OpenListResourceBundle extends ResourceBundle {
|
|||||||
return new HashSet<>();
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private volatile Map<String, Object> lookup;
|
private final Supplier<Map<String, Object>> lookup = StableValue.supplier(
|
||||||
private volatile Set<String> keyset;
|
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