8036936: Use local locales
Summary: Made sure cache key is cleare on GC invocation
Reviewed-by: okutsu
--- a/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java Mon Apr 14 21:02:31 2014 +0000
+++ b/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java Mon Apr 21 11:08:30 2014 -0700
@@ -31,6 +31,7 @@
*/
package sun.util.locale;
+import java.lang.ref.SoftReference;
import java.util.StringJoiner;
@@ -151,11 +152,11 @@
return h;
}
- private static final class Key implements Comparable<Key> {
- private final String lang;
- private final String scrt;
- private final String regn;
- private final String vart;
+ private static final class Key {
+ private final SoftReference<String> lang;
+ private final SoftReference<String> scrt;
+ private final SoftReference<String> regn;
+ private final SoftReference<String> vart;
private final boolean normalized;
private final int hash;
@@ -167,10 +168,10 @@
assert language.intern() == language
&& region.intern() == region;
- lang = language;
- scrt = "";
- regn = region;
- vart = "";
+ lang = new SoftReference<>(language);
+ scrt = new SoftReference<>("");
+ regn = new SoftReference<>(region);
+ vart = new SoftReference<>("");
this.normalized = true;
int h = language.hashCode();
@@ -191,40 +192,40 @@
String variant, boolean normalized) {
int h = 0;
if (language != null) {
- lang = language;
+ lang = new SoftReference<>(language);
int len = language.length();
for (int i = 0; i < len; i++) {
h = 31*h + LocaleUtils.toLower(language.charAt(i));
}
} else {
- lang = "";
+ lang = new SoftReference<>("");
}
if (script != null) {
- scrt = script;
+ scrt = new SoftReference<>(script);
int len = script.length();
for (int i = 0; i < len; i++) {
h = 31*h + LocaleUtils.toLower(script.charAt(i));
}
} else {
- scrt = "";
+ scrt = new SoftReference<>("");
}
if (region != null) {
- regn = region;
+ regn = new SoftReference<>(region);
int len = region.length();
for (int i = 0; i < len; i++) {
h = 31*h + LocaleUtils.toLower(region.charAt(i));
}
} else {
- regn = "";
+ regn = new SoftReference<>("");
}
if (variant != null) {
- vart = variant;
+ vart = new SoftReference<>(variant);
int len = variant.length();
for (int i = 0; i < len; i++) {
h = 31*h + variant.charAt(i);
}
} else {
- vart = "";
+ vart = new SoftReference<>("");
}
hash = h;
this.normalized = normalized;
@@ -232,28 +233,31 @@
@Override
public boolean equals(Object obj) {
- return (this == obj) ||
- (obj instanceof Key)
- && this.hash == ((Key)obj).hash
- && LocaleUtils.caseIgnoreMatch(((Key)obj).lang, this.lang)
- && LocaleUtils.caseIgnoreMatch(((Key)obj).scrt, this.scrt)
- && LocaleUtils.caseIgnoreMatch(((Key)obj).regn, this.regn)
- && ((Key)obj).vart.equals(vart); // variant is case sensitive in JDK!
- }
+ if (this == obj) {
+ return true;
+ }
- @Override
- public int compareTo(Key other) {
- int res = LocaleUtils.caseIgnoreCompare(this.lang, other.lang);
- if (res == 0) {
- res = LocaleUtils.caseIgnoreCompare(this.scrt, other.scrt);
- if (res == 0) {
- res = LocaleUtils.caseIgnoreCompare(this.regn, other.regn);
- if (res == 0) {
- res = this.vart.compareTo(other.vart);
+ if (obj instanceof Key && this.hash == ((Key)obj).hash) {
+ String tl = this.lang.get();
+ String ol = ((Key)obj).lang.get();
+ if (tl != null && ol != null &&
+ LocaleUtils.caseIgnoreMatch(ol, tl)) {
+ String ts = this.scrt.get();
+ String os = ((Key)obj).scrt.get();
+ if (ts != null && os != null &&
+ LocaleUtils.caseIgnoreMatch(os, ts)) {
+ String tr = this.regn.get();
+ String or = ((Key)obj).regn.get();
+ if (tr != null && or != null &&
+ LocaleUtils.caseIgnoreMatch(or, tr)) {
+ String tv = this.vart.get();
+ String ov = ((Key)obj).vart.get();
+ return (ov != null && ov.equals(tv));
+ }
}
}
}
- return res;
+ return false;
}
@Override
@@ -266,10 +270,10 @@
return key;
}
- String lang = LocaleUtils.toLowerString(key.lang).intern();
- String scrt = LocaleUtils.toTitleString(key.scrt).intern();
- String regn = LocaleUtils.toUpperString(key.regn).intern();
- String vart = key.vart.intern(); // preserve upper/lower cases
+ String lang = LocaleUtils.toLowerString(key.lang.get()).intern();
+ String scrt = LocaleUtils.toTitleString(key.scrt.get()).intern();
+ String regn = LocaleUtils.toUpperString(key.regn.get()).intern();
+ String vart = key.vart.get().intern(); // preserve upper/lower cases
return new Key(lang, scrt, regn, vart, true);
}
@@ -282,12 +286,18 @@
@Override
protected Key normalizeKey(Key key) {
+ assert key.lang.get() != null &&
+ key.scrt.get() != null &&
+ key.regn.get() != null &&
+ key.vart.get() != null;
+
return Key.normalize(key);
}
@Override
protected BaseLocale createObject(Key key) {
- return new BaseLocale(key.lang, key.scrt, key.regn, key.vart);
+ return new BaseLocale(key.lang.get(), key.scrt.get(),
+ key.regn.get(), key.vart.get());
}
}
}
--- a/jdk/src/java.base/share/classes/sun/util/locale/LocaleObjectCache.java Mon Apr 14 21:02:31 2014 +0000
+++ b/jdk/src/java.base/share/classes/sun/util/locale/LocaleObjectCache.java Mon Apr 21 11:08:30 2014 -0700
@@ -57,8 +57,10 @@
value = entry.get();
}
if (value == null) {
+ V newVal = createObject(key);
+ // make sure key is normalized *after* the object creation
+ // so that newVal is assured to be created from a valid key.
key = normalizeKey(key);
- V newVal = createObject(key);
if (key == null || newVal == null) {
// subclass must return non-null key/value object
return null;