< prev index next >

src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template

Print this page
rev 17642 : 8186517: sun.nio.cs.StandardCharsets$Aliases and Classes can be lazily loaded
Reviewed-by: sherman, martin, plevart

*** 31,75 **** import java.nio.charset.Charset; import java.nio.charset.spi.CharsetProvider; import java.util.Iterator; import java.util.Map; import sun.security.action.GetPropertyAction; public class StandardCharsets extends CharsetProvider { _INCLUDE_ALIASES_TABLES_ _INCLUDE_ALIASES_MAP_ _INCLUDE_CLASSES_MAP_ _INCLUDE_CACHE_MAP_ // Maps canonical names to class names ! private final Map<String,String> classMap; ! // Maps alias names to canonical names ! private final Map<String,String> aliasMap; ! // Maps canonical names to cached instances ! private final Map<String,Charset> cache; ! ! private static final String packagePrefix = "sun.nio.cs"; ! public static final String US_ASCII = "US-ASCII"; ! public static final String ISO_8859_1 = "ISO-8859-1"; ! public static final String UTF_8 = "UTF-8"; public StandardCharsets() { - this.aliasMap = new Aliases(); - this.classMap = new Classes(); - this.cache = new Cache(); } private String canonicalize(String csn) { ! String acn = aliasMap.get(csn); return (acn != null) ? acn : csn; } // Private ASCII-only version, optimized for interpretation during startup // private static String toLower(String s) { int n = s.length(); boolean allLower = true; --- 31,98 ---- import java.nio.charset.Charset; import java.nio.charset.spi.CharsetProvider; import java.util.Iterator; import java.util.Map; + import java.util.Set; + import jdk.internal.vm.annotation.Stable; import sun.security.action.GetPropertyAction; public class StandardCharsets extends CharsetProvider { _INCLUDE_ALIASES_TABLES_ _INCLUDE_ALIASES_MAP_ _INCLUDE_CLASSES_MAP_ _INCLUDE_CACHE_MAP_ // Maps canonical names to class names ! private @Stable Map<String,String> classMap; ! // Maps alias names to canonical names ! private @Stable Map<String,String> aliasMap; ! // Maps canonical names to cached instances ! private @Stable Map<String,Charset> cache; ! private static final String packagePrefix = "sun.nio.cs."; public StandardCharsets() { } private String canonicalize(String csn) { ! String acn = aliasMap().get(csn); return (acn != null) ? acn : csn; } + private Map<String,String> aliasMap() { + Map<String,String> map = aliasMap; + if (map == null) { + aliasMap = map = new Aliases(); + } + return map; + } + + private Map<String,String> classMap() { + Map<String,String> map = classMap; + if (map == null) { + classMap = map = new Classes(); + } + return map; + } + + private Map<String,Charset> cache() { + Map<String,Charset> map = cache; + if (map == null) { + map = new Cache(); + map.put("utf-8", UTF_8.INSTANCE); + map.put("iso-8859-1", ISO_8859_1.INSTANCE); + map.put("us-ascii", US_ASCII.INSTANCE); + cache = map; + } + return map; + } + // Private ASCII-only version, optimized for interpretation during startup // private static String toLower(String s) { int n = s.length(); boolean allLower = true;
*** 80,130 **** break; } } if (allLower) return s; ! char[] ca = new char[n]; for (int i = 0; i < n; i++) { int c = s.charAt(i); if (((c - 'A') | ('Z' - c)) >= 0) ! ca[i] = (char)(c + 0x20); else ! ca[i] = (char)c; } ! return new String(ca); } private Charset lookup(String charsetName) { init(); ! String csn = canonicalize(toLower(charsetName)); // Check cache first ! Charset cs = cache.get(csn); if (cs != null) return cs; // Do we even support this charset? ! String cln = classMap.get(csn); if (cln == null) return null; - // As all charset class names added to classMap are string literals we - // can check identity here as an optimization - if (cln == US_ASCII) { - return cache(csn, new US_ASCII()); - } - if (cln == ISO_8859_1) { - return cache(csn, new ISO_8859_1()); - } - if (cln == UTF_8) { - return cache(csn, new UTF_8()); - } - // Instantiate the charset and cache it try { @SuppressWarnings("deprecation") ! Object o = Class.forName(packagePrefix + "." + cln, true, this.getClass().getClassLoader()).newInstance(); return cache(csn, (Charset)o); } catch (ClassNotFoundException | IllegalAccessException | --- 103,153 ---- break; } } if (allLower) return s; ! StringBuilder sb = new StringBuilder(n); for (int i = 0; i < n; i++) { int c = s.charAt(i); if (((c - 'A') | ('Z' - c)) >= 0) ! sb.append((char)(c + 0x20)); else ! sb.append((char)c); } ! return sb.toString(); } private Charset lookup(String charsetName) { init(); ! ! // By checking these built-ins we can avoid initializing Aliases and ! // Classes eagerly during bootstrap ! String csn; ! if (charsetName.equals("UTF-8")) { ! return UTF_8.INSTANCE; ! } else if (charsetName.equals("US-ASCII")) { ! return US_ASCII.INSTANCE; ! } else if (charsetName.equals("ISO-8859-1")) { ! return ISO_8859_1.INSTANCE; ! } else { ! csn = canonicalize(toLower(charsetName)); ! } // Check cache first ! Charset cs = cache().get(csn); if (cs != null) return cs; // Do we even support this charset? ! String cln = classMap().get(csn); if (cln == null) return null; // Instantiate the charset and cache it try { @SuppressWarnings("deprecation") ! Object o = Class.forName(packagePrefix + cln, true, this.getClass().getClassLoader()).newInstance(); return cache(csn, (Charset)o); } catch (ClassNotFoundException | IllegalAccessException |
*** 132,158 **** return null; } } private Charset cache(String csn, Charset cs) { ! cache.put(csn, cs); return cs; } public final Charset charsetForName(String charsetName) { synchronized (this) { ! return lookup(canonicalize(charsetName)); } } public final Iterator<Charset> charsets() { synchronized (this) { init(); } return new Iterator<Charset>() { ! Iterator<String> i = classMap.keySet().iterator(); public boolean hasNext() { return i.hasNext(); } --- 155,186 ---- return null; } } private Charset cache(String csn, Charset cs) { ! cache().put(csn, cs); return cs; } public final Charset charsetForName(String charsetName) { synchronized (this) { ! return lookup(charsetName); } } public final Iterator<Charset> charsets() { + Set<String> charsetNames; synchronized (this) { init(); + // Ensure initialized in synchronized block + charsetNames = classMap().keySet(); + aliasMap(); + cache(); } return new Iterator<Charset>() { ! Iterator<String> i = charsetNames.iterator(); public boolean hasNext() { return i.hasNext(); }
*** 179,188 **** --- 207,218 ---- return; initialized = true; String map = GetPropertyAction.privilegedGetProperty("sun.nio.cs.map"); if (map != null) { + Map<String,String> aliasMap = aliasMap(); + Map<String,String> classMap = classMap(); String[] maps = map.split(","); for (int i = 0; i < maps.length; i++) { if (maps[i].equalsIgnoreCase("Windows-31J/Shift_JIS")) { // if we dont have both sjis and ms932, do nothing if (classMap.get("shift_jis") == null ||
*** 205,215 **** aliases_SJIS = new String[] { "sjis" }; for (String alias : aliases_MS932) { aliasMap.put(toLower(alias), "windows-31j"); } ! cache.put("shift_jis", null); break; } } } } --- 235,245 ---- aliases_SJIS = new String[] { "sjis" }; for (String alias : aliases_MS932) { aliasMap.put(toLower(alias), "windows-31j"); } ! cache().put("shift_jis", null); break; } } } }
< prev index next >