8036936: Use local locales
authornaoto
Mon, 21 Apr 2014 11:08:30 -0700
changeset 27067 0e748d185207
parent 27066 d3f0b8d935e6
child 27068 5fe2d67f5f68
8036936: Use local locales Summary: Made sure cache key is cleare on GC invocation Reviewed-by: okutsu
jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java
jdk/src/java.base/share/classes/sun/util/locale/LocaleObjectCache.java
--- 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;