mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-15 08:34:30 +02:00
8186517: sun.nio.cs.StandardCharsets$Aliases and Classes can be lazily loaded
Reviewed-by: sherman, martin, plevart
This commit is contained in:
parent
cfe34ed89c
commit
a0564d954d
21 changed files with 116 additions and 75 deletions
|
@ -179,7 +179,7 @@ public class DBCS {
|
|||
.replace("$NAME_CLZ$", clzName)
|
||||
.replace("$NAME_ALIASES$",
|
||||
"sun.nio.cs".equals(pkgName) ?
|
||||
"StandardCharsets.aliases_" + clzName :
|
||||
"StandardCharsets.aliases_" + clzName + "()" :
|
||||
"ExtendedCharsets.aliasesFor(\"" + csName + "\")")
|
||||
.replace("$NAME_CS$" , csName)
|
||||
.replace("$CONTAINS$",
|
||||
|
|
|
@ -161,7 +161,7 @@ public class SBCS {
|
|||
if (line.indexOf("$NAME_ALIASES$", i) != -1) {
|
||||
if ("sun.nio.cs".equals(pkgName))
|
||||
line = line.replace("$NAME_ALIASES$",
|
||||
"StandardCharsets.aliases_" + clzName);
|
||||
"StandardCharsets.aliases_" + clzName + "()");
|
||||
else
|
||||
line = line.replace("$NAME_ALIASES$",
|
||||
"ExtendedCharsets.aliasesFor(\"" + csName + "\")");
|
||||
|
|
|
@ -93,21 +93,28 @@ public class SPI {
|
|||
.filter(cs -> cs.pkgName.equals("sun.nio.cs"))
|
||||
.forEach( cs -> {
|
||||
if (cs.aliases == null || cs.aliases.length == 0) {
|
||||
out.printf(" static final String[] aliases_%s = null;%n%n",
|
||||
out.printf(" static String[] aliases_%s() { return null; }%n%n",
|
||||
cs.clzName);
|
||||
} else {
|
||||
boolean methodEnd = true;
|
||||
// non-final for SJIS and MS932 to support sun.nio.cs.map
|
||||
if (cs.clzName.equals("SJIS") || cs.clzName.equals("MS932")) {
|
||||
out.printf(" static String[] aliases_%s() { return aliases_%s; }%n%n",
|
||||
cs.clzName, cs.clzName);
|
||||
out.printf(" static String[] aliases_%s = new String[] {%n",
|
||||
cs.clzName);
|
||||
methodEnd = false;
|
||||
} else {
|
||||
out.printf(" static final String[] aliases_%s = new String[] {%n",
|
||||
out.printf(" static String[] aliases_%s() { return new String[] {%n",
|
||||
cs.clzName);
|
||||
}
|
||||
for (String alias : cs.aliases) {
|
||||
out.printf(" \"%s\",%n", alias);
|
||||
out.printf(" \"%s\",%n", alias);
|
||||
}
|
||||
out.printf(" };%n%n");
|
||||
if (methodEnd) {
|
||||
out.printf(" }%n%n");
|
||||
}
|
||||
out.printf(" };%n%n");
|
||||
}
|
||||
});
|
||||
Charset cs = charsets.get("SJIS");
|
||||
|
|
|
@ -51,7 +51,7 @@ public class SRC {
|
|||
} else if (line.indexOf("$ALIASES$") != -1) {
|
||||
if ("sun.nio.cs".equals(pkgName))
|
||||
out.println(line.replace("$ALIASES$",
|
||||
"StandardCharsets.aliases_" + clzName));
|
||||
"StandardCharsets.aliases_" + clzName + "()"));
|
||||
else
|
||||
out.println(line.replace("$ALIASES$",
|
||||
"ExtendedCharsets.aliasesFor(\"" + csName + "\")"));
|
||||
|
|
|
@ -42,6 +42,7 @@ import jdk.internal.HotSpotIntrinsicCandidate;
|
|||
import sun.nio.cs.HistoricallyNamedCharset;
|
||||
import sun.nio.cs.ArrayDecoder;
|
||||
import sun.nio.cs.ArrayEncoder;
|
||||
import sun.nio.cs.StandardCharsets;
|
||||
|
||||
import static java.lang.String.LATIN1;
|
||||
import static java.lang.String.UTF16;
|
||||
|
@ -61,9 +62,9 @@ class StringCoding {
|
|||
private static final ThreadLocal<SoftReference<StringEncoder>> encoder =
|
||||
new ThreadLocal<>();
|
||||
|
||||
private static final Charset ISO_8859_1 = Charset.forName("iso-8859-1");
|
||||
private static final Charset US_ASCII = Charset.forName("us-ascii");
|
||||
private static final Charset UTF_8 = Charset.forName("utf-8");
|
||||
private static final Charset ISO_8859_1 = sun.nio.cs.ISO_8859_1.INSTANCE;
|
||||
private static final Charset US_ASCII = sun.nio.cs.US_ASCII.INSTANCE;
|
||||
private static final Charset UTF_8 = sun.nio.cs.UTF_8.INSTANCE;
|
||||
|
||||
private static boolean warnUnsupportedCharset = true;
|
||||
|
||||
|
|
|
@ -609,7 +609,7 @@ public abstract class Charset
|
|||
if (cs != null)
|
||||
defaultCharset = cs;
|
||||
else
|
||||
defaultCharset = forName("UTF-8");
|
||||
defaultCharset = sun.nio.cs.UTF_8.INSTANCE;
|
||||
}
|
||||
}
|
||||
return defaultCharset;
|
||||
|
@ -639,11 +639,10 @@ public abstract class Charset
|
|||
String[] as = Objects.requireNonNullElse(aliases, zeroAliases);
|
||||
|
||||
// Skip checks for the standard, built-in Charsets we always load
|
||||
// during initialization. Use of identity is intentional to be
|
||||
// consistent with sun.nio.cs.StandardCharsets
|
||||
if (canonicalName != StandardCharsets.ISO_8859_1
|
||||
&& canonicalName != StandardCharsets.US_ASCII
|
||||
&& canonicalName != StandardCharsets.UTF_8) {
|
||||
// during initialization.
|
||||
if (canonicalName != "ISO-8859-1"
|
||||
&& canonicalName != "US-ASCII"
|
||||
&& canonicalName != "UTF-8") {
|
||||
checkName(canonicalName);
|
||||
for (int i = 0; i < as.length; i++) {
|
||||
checkName(as[i]);
|
||||
|
|
|
@ -41,15 +41,15 @@ public final class StandardCharsets {
|
|||
* Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the
|
||||
* Unicode character set
|
||||
*/
|
||||
public static final Charset US_ASCII = Charset.forName("US-ASCII");
|
||||
public static final Charset US_ASCII = sun.nio.cs.US_ASCII.INSTANCE;
|
||||
/**
|
||||
* ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1
|
||||
*/
|
||||
public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
|
||||
public static final Charset ISO_8859_1 = sun.nio.cs.ISO_8859_1.INSTANCE;
|
||||
/**
|
||||
* Eight-bit UCS Transformation Format
|
||||
*/
|
||||
public static final Charset UTF_8 = Charset.forName("UTF-8");
|
||||
public static final Charset UTF_8 = sun.nio.cs.UTF_8.INSTANCE;
|
||||
/**
|
||||
* Sixteen-bit UCS Transformation Format, big-endian byte order
|
||||
*/
|
||||
|
|
|
@ -52,7 +52,7 @@ import java.nio.charset.CodingErrorAction;
|
|||
class CESU_8 extends Unicode
|
||||
{
|
||||
public CESU_8() {
|
||||
super("CESU-8", StandardCharsets.aliases_CESU_8);
|
||||
super("CESU-8", StandardCharsets.aliases_CESU_8());
|
||||
}
|
||||
|
||||
public String historicalName() {
|
||||
|
|
|
@ -31,18 +31,19 @@ import java.nio.charset.Charset;
|
|||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.nio.charset.CoderResult;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
|
||||
class ISO_8859_1
|
||||
public class ISO_8859_1
|
||||
extends Charset
|
||||
implements HistoricallyNamedCharset
|
||||
{
|
||||
|
||||
public static final ISO_8859_1 INSTANCE = new ISO_8859_1();
|
||||
|
||||
public ISO_8859_1() {
|
||||
super(StandardCharsets.ISO_8859_1, StandardCharsets.aliases_ISO_8859_1);
|
||||
super("ISO-8859-1", StandardCharsets.aliases_ISO_8859_1());
|
||||
}
|
||||
|
||||
public String historicalName() {
|
||||
|
|
|
@ -33,6 +33,8 @@ 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 {
|
||||
|
@ -43,31 +45,52 @@ public class StandardCharsets extends CharsetProvider {
|
|||
_INCLUDE_CACHE_MAP_
|
||||
|
||||
// Maps canonical names to class names
|
||||
private final Map<String,String> classMap;
|
||||
private @Stable Map<String,String> classMap;
|
||||
|
||||
// Maps alias names to canonical names
|
||||
private final Map<String,String> aliasMap;
|
||||
private @Stable Map<String,String> aliasMap;
|
||||
|
||||
// Maps canonical names to cached instances
|
||||
private final Map<String,Charset> cache;
|
||||
private @Stable 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";
|
||||
private static final String packagePrefix = "sun.nio.cs.";
|
||||
|
||||
public StandardCharsets() {
|
||||
this.aliasMap = new Aliases();
|
||||
this.classMap = new Classes();
|
||||
this.cache = new Cache();
|
||||
}
|
||||
|
||||
private String canonicalize(String csn) {
|
||||
String acn = aliasMap.get(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) {
|
||||
|
@ -82,47 +105,47 @@ public class StandardCharsets extends CharsetProvider {
|
|||
}
|
||||
if (allLower)
|
||||
return s;
|
||||
char[] ca = new char[n];
|
||||
StringBuilder sb = new StringBuilder(n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
int c = s.charAt(i);
|
||||
if (((c - 'A') | ('Z' - c)) >= 0)
|
||||
ca[i] = (char)(c + 0x20);
|
||||
sb.append((char)(c + 0x20));
|
||||
else
|
||||
ca[i] = (char)c;
|
||||
sb.append((char)c);
|
||||
}
|
||||
return new String(ca);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private Charset lookup(String charsetName) {
|
||||
init();
|
||||
String csn = canonicalize(toLower(charsetName));
|
||||
|
||||
// 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);
|
||||
Charset cs = cache().get(csn);
|
||||
if (cs != null)
|
||||
return cs;
|
||||
|
||||
// Do we even support this charset?
|
||||
String cln = classMap.get(csn);
|
||||
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,
|
||||
Object o = Class.forName(packagePrefix + cln,
|
||||
true,
|
||||
this.getClass().getClassLoader()).newInstance();
|
||||
return cache(csn, (Charset)o);
|
||||
|
@ -134,23 +157,28 @@ public class StandardCharsets extends CharsetProvider {
|
|||
}
|
||||
|
||||
private Charset cache(String csn, Charset cs) {
|
||||
cache.put(csn, cs);
|
||||
cache().put(csn, cs);
|
||||
return cs;
|
||||
}
|
||||
|
||||
public final Charset charsetForName(String charsetName) {
|
||||
synchronized (this) {
|
||||
return lookup(canonicalize(charsetName));
|
||||
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 = classMap.keySet().iterator();
|
||||
Iterator<String> i = charsetNames.iterator();
|
||||
|
||||
public boolean hasNext() {
|
||||
return i.hasNext();
|
||||
|
@ -181,6 +209,8 @@ public class StandardCharsets extends CharsetProvider {
|
|||
|
||||
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")) {
|
||||
|
@ -207,7 +237,7 @@ public class StandardCharsets extends CharsetProvider {
|
|||
for (String alias : aliases_MS932) {
|
||||
aliasMap.put(toLower(alias), "windows-31j");
|
||||
}
|
||||
cache.put("shift_jis", null);
|
||||
cache().put("shift_jis", null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,9 +36,10 @@ public class US_ASCII
|
|||
extends Charset
|
||||
implements HistoricallyNamedCharset
|
||||
{
|
||||
public static final US_ASCII INSTANCE = new US_ASCII();
|
||||
|
||||
public US_ASCII() {
|
||||
super(StandardCharsets.US_ASCII, StandardCharsets.aliases_US_ASCII);
|
||||
super("US-ASCII", StandardCharsets.aliases_US_ASCII());
|
||||
}
|
||||
|
||||
public String historicalName() {
|
||||
|
|
|
@ -33,7 +33,7 @@ class UTF_16 extends Unicode
|
|||
{
|
||||
|
||||
public UTF_16() {
|
||||
super("UTF-16", StandardCharsets.aliases_UTF_16);
|
||||
super("UTF-16", StandardCharsets.aliases_UTF_16());
|
||||
}
|
||||
|
||||
public String historicalName() {
|
||||
|
|
|
@ -33,7 +33,7 @@ class UTF_16BE extends Unicode
|
|||
{
|
||||
|
||||
public UTF_16BE() {
|
||||
super("UTF-16BE", StandardCharsets.aliases_UTF_16BE);
|
||||
super("UTF-16BE", StandardCharsets.aliases_UTF_16BE());
|
||||
}
|
||||
|
||||
public String historicalName() {
|
||||
|
|
|
@ -33,7 +33,7 @@ class UTF_16LE extends Unicode
|
|||
{
|
||||
|
||||
public UTF_16LE() {
|
||||
super("UTF-16LE", StandardCharsets.aliases_UTF_16LE);
|
||||
super("UTF-16LE", StandardCharsets.aliases_UTF_16LE());
|
||||
}
|
||||
|
||||
public String historicalName() {
|
||||
|
|
|
@ -33,7 +33,7 @@ class UTF_16LE_BOM extends Unicode
|
|||
{
|
||||
|
||||
public UTF_16LE_BOM() {
|
||||
super("x-UTF-16LE-BOM", StandardCharsets.aliases_UTF_16LE_BOM);
|
||||
super("x-UTF-16LE-BOM", StandardCharsets.aliases_UTF_16LE_BOM());
|
||||
}
|
||||
|
||||
public String historicalName() {
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.nio.charset.CharsetEncoder;
|
|||
public class UTF_32 extends Unicode
|
||||
{
|
||||
public UTF_32() {
|
||||
super("UTF-32", StandardCharsets.aliases_UTF_32);
|
||||
super("UTF-32", StandardCharsets.aliases_UTF_32());
|
||||
}
|
||||
|
||||
public String historicalName() {
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.nio.charset.CharsetEncoder;
|
|||
public class UTF_32BE extends Unicode
|
||||
{
|
||||
public UTF_32BE() {
|
||||
super("UTF-32BE", StandardCharsets.aliases_UTF_32BE);
|
||||
super("UTF-32BE", StandardCharsets.aliases_UTF_32BE());
|
||||
}
|
||||
|
||||
public String historicalName() {
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.nio.charset.CharsetEncoder;
|
|||
public class UTF_32BE_BOM extends Unicode
|
||||
{
|
||||
public UTF_32BE_BOM() {
|
||||
super("X-UTF-32BE-BOM", StandardCharsets.aliases_UTF_32BE_BOM);
|
||||
super("X-UTF-32BE-BOM", StandardCharsets.aliases_UTF_32BE_BOM());
|
||||
}
|
||||
|
||||
public String historicalName() {
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.nio.charset.CharsetEncoder;
|
|||
public class UTF_32LE extends Unicode
|
||||
{
|
||||
public UTF_32LE() {
|
||||
super("UTF-32LE", StandardCharsets.aliases_UTF_32LE);
|
||||
super("UTF-32LE", StandardCharsets.aliases_UTF_32LE());
|
||||
}
|
||||
|
||||
public String historicalName() {
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.nio.charset.CharsetEncoder;
|
|||
public class UTF_32LE_BOM extends Unicode
|
||||
{
|
||||
public UTF_32LE_BOM() {
|
||||
super("X-UTF-32LE-BOM", StandardCharsets.aliases_UTF_32LE_BOM);
|
||||
super("X-UTF-32LE-BOM", StandardCharsets.aliases_UTF_32LE_BOM());
|
||||
}
|
||||
|
||||
public String historicalName() {
|
||||
|
|
|
@ -54,10 +54,12 @@ import java.nio.charset.CodingErrorAction;
|
|||
*
|
||||
*/
|
||||
|
||||
class UTF_8 extends Unicode
|
||||
{
|
||||
public final class UTF_8 extends Unicode {
|
||||
|
||||
public static final UTF_8 INSTANCE = new UTF_8();
|
||||
|
||||
public UTF_8() {
|
||||
super(StandardCharsets.UTF_8, StandardCharsets.aliases_UTF_8);
|
||||
super("UTF-8", StandardCharsets.aliases_UTF_8());
|
||||
}
|
||||
|
||||
public String historicalName() {
|
||||
|
@ -72,7 +74,7 @@ class UTF_8 extends Unicode
|
|||
return new Encoder(this);
|
||||
}
|
||||
|
||||
private static final void updatePositions(Buffer src, int sp,
|
||||
static final void updatePositions(Buffer src, int sp,
|
||||
Buffer dst, int dp) {
|
||||
src.position(sp - src.arrayOffset());
|
||||
dst.position(dp - dst.arrayOffset());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue