# HG changeset patch # User redestad # Date 1523276956 -7200 # Mon Apr 09 14:29:16 2018 +0200 # Node ID 5bb18aa1d8fb57ea1003ab3db8e0b69ed101d7f1 # Parent 1975a94f16ccdf3cf4630893da3c63359a4bdb95 8201179: Regression due loading java.nio.charset.StandardCharsets during bootstrap Reviewed-by: sherman diff --git a/src/java.base/share/classes/java/lang/CharacterName.java b/src/java.base/share/classes/java/lang/CharacterName.java --- a/src/java.base/share/classes/java/lang/CharacterName.java +++ b/src/java.base/share/classes/java/lang/CharacterName.java @@ -29,11 +29,12 @@ import java.io.InputStream; import java.lang.ref.SoftReference; import java.util.Arrays; -import java.util.Locale; import java.util.zip.InflaterInputStream; import java.security.AccessController; import java.security.PrivilegedAction; +import sun.nio.cs.ISO_8859_1; + class CharacterName { private static SoftReference refCharName; @@ -151,7 +152,7 @@ } public int getCodePoint(String name) { - byte[] bname = name.getBytes(java.nio.charset.StandardCharsets.ISO_8859_1); + byte[] bname = name.getBytes(ISO_8859_1.INSTANCE); int hsh = hashN(bname, 0, bname.length); int idx = hsIndices[(hsh & 0x7fffffff) % hsIndices.length]; while (idx != -1) { diff --git a/src/java.base/share/classes/java/lang/StringCoding.java b/src/java.base/share/classes/java/lang/StringCoding.java --- a/src/java.base/share/classes/java/lang/StringCoding.java +++ b/src/java.base/share/classes/java/lang/StringCoding.java @@ -42,7 +42,6 @@ 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; @@ -52,9 +51,6 @@ import static java.lang.Character.lowSurrogate; import static java.lang.Character.isSupplementaryCodePoint; import static java.lang.StringUTF16.putChar; -import static java.nio.charset.StandardCharsets.ISO_8859_1; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; /** * Utility class for string encoding and decoding. @@ -70,6 +66,10 @@ private static final ThreadLocal> encoder = new ThreadLocal<>(); + 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 T deref(ThreadLocal> tl) { SoftReference sr = tl.get(); if (sr == null) diff --git a/src/java.base/share/classes/java/nio/charset/Charset.java b/src/java.base/share/classes/java/nio/charset/Charset.java --- a/src/java.base/share/classes/java/nio/charset/Charset.java +++ b/src/java.base/share/classes/java/nio/charset/Charset.java @@ -609,7 +609,7 @@ if (cs != null) defaultCharset = cs; else - defaultCharset = StandardCharsets.UTF_8; + defaultCharset = sun.nio.cs.UTF_8.INSTANCE; } } return defaultCharset; diff --git a/src/java.base/share/classes/java/nio/charset/StandardCharsets.java b/src/java.base/share/classes/java/nio/charset/StandardCharsets.java --- a/src/java.base/share/classes/java/nio/charset/StandardCharsets.java +++ b/src/java.base/share/classes/java/nio/charset/StandardCharsets.java @@ -34,33 +34,39 @@ */ public final class StandardCharsets { + // To avoid accidental eager initialization of often unused Charsets + // from happening while the VM is booting up, which may delay + // initialization of VM components, we should generally avoid depending + // on this class from elsewhere in java.base. + private StandardCharsets() { throw new AssertionError("No java.nio.charset.StandardCharsets instances for you!"); } + /** * 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 = new sun.nio.cs.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 = new sun.nio.cs.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 = new sun.nio.cs.UTF_8(); + public static final Charset UTF_8 = sun.nio.cs.UTF_8.INSTANCE; /** * Sixteen-bit UCS Transformation Format, big-endian byte order */ - public static final Charset UTF_16BE = new sun.nio.cs.UTF_16BE(); + public static final Charset UTF_16BE = sun.nio.cs.UTF_16BE.INSTANCE; /** * Sixteen-bit UCS Transformation Format, little-endian byte order */ - public static final Charset UTF_16LE = new sun.nio.cs.UTF_16LE(); + public static final Charset UTF_16LE = sun.nio.cs.UTF_16LE.INSTANCE; /** * Sixteen-bit UCS Transformation Format, byte order identified by an * optional byte-order mark */ - public static final Charset UTF_16 = new sun.nio.cs.UTF_16(); + public static final Charset UTF_16 = sun.nio.cs.UTF_16.INSTANCE; } diff --git a/src/java.base/share/classes/java/nio/file/FileChannelLinesSpliterator.java b/src/java.base/share/classes/java/nio/file/FileChannelLinesSpliterator.java --- a/src/java.base/share/classes/java/nio/file/FileChannelLinesSpliterator.java +++ b/src/java.base/share/classes/java/nio/file/FileChannelLinesSpliterator.java @@ -32,12 +32,15 @@ import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.util.HashSet; import java.util.Set; import java.util.Spliterator; import java.util.function.Consumer; +import sun.nio.cs.ISO_8859_1; +import sun.nio.cs.US_ASCII; +import sun.nio.cs.UTF_8; + /** * A file-based lines spliterator, leveraging a shared mapped byte buffer and * associated file channel, covering lines of a file for character encodings @@ -66,9 +69,9 @@ static final Set SUPPORTED_CHARSET_NAMES; static { SUPPORTED_CHARSET_NAMES = new HashSet<>(); - SUPPORTED_CHARSET_NAMES.add(StandardCharsets.UTF_8.name()); - SUPPORTED_CHARSET_NAMES.add(StandardCharsets.ISO_8859_1.name()); - SUPPORTED_CHARSET_NAMES.add(StandardCharsets.US_ASCII.name()); + SUPPORTED_CHARSET_NAMES.add(UTF_8.INSTANCE.name()); + SUPPORTED_CHARSET_NAMES.add(ISO_8859_1.INSTANCE.name()); + SUPPORTED_CHARSET_NAMES.add(US_ASCII.INSTANCE.name()); } private final FileChannel fc; diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -77,6 +77,7 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; +import sun.nio.cs.UTF_8; import sun.nio.fs.AbstractFileSystemProvider; /** @@ -2859,7 +2860,7 @@ * @since 1.8 */ public static BufferedReader newBufferedReader(Path path) throws IOException { - return newBufferedReader(path, StandardCharsets.UTF_8); + return newBufferedReader(path, UTF_8.INSTANCE); } /** @@ -2951,7 +2952,7 @@ public static BufferedWriter newBufferedWriter(Path path, OpenOption... options) throws IOException { - return newBufferedWriter(path, StandardCharsets.UTF_8, options); + return newBufferedWriter(path, UTF_8.INSTANCE, options); } /** @@ -3281,7 +3282,7 @@ * @since 1.8 */ public static List readAllLines(Path path) throws IOException { - return readAllLines(path, StandardCharsets.UTF_8); + return readAllLines(path, UTF_8.INSTANCE); } /** @@ -3452,7 +3453,7 @@ OpenOption... options) throws IOException { - return write(path, lines, StandardCharsets.UTF_8, options); + return write(path, lines, UTF_8.INSTANCE, options); } // -- Stream APIs -- @@ -3939,6 +3940,6 @@ * @since 1.8 */ public static Stream lines(Path path) throws IOException { - return lines(path, StandardCharsets.UTF_8); + return lines(path, UTF_8.INSTANCE); } } diff --git a/src/java.base/share/classes/java/util/Base64.java b/src/java.base/share/classes/java/util/Base64.java --- a/src/java.base/share/classes/java/util/Base64.java +++ b/src/java.base/share/classes/java/util/Base64.java @@ -30,7 +30,8 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; + +import sun.nio.cs.ISO_8859_1; /** * This class consists exclusively of static methods for obtaining @@ -548,7 +549,7 @@ * if {@code src} is not in valid Base64 scheme */ public byte[] decode(String src) { - return decode(src.getBytes(StandardCharsets.ISO_8859_1)); + return decode(src.getBytes(ISO_8859_1.INSTANCE)); } /** diff --git a/src/java.base/share/classes/java/util/PropertyResourceBundle.java b/src/java.base/share/classes/java/util/PropertyResourceBundle.java --- a/src/java.base/share/classes/java/util/PropertyResourceBundle.java +++ b/src/java.base/share/classes/java/util/PropertyResourceBundle.java @@ -44,8 +44,9 @@ import java.io.Reader; import java.io.IOException; import java.nio.charset.MalformedInputException; -import java.nio.charset.StandardCharsets; import java.nio.charset.UnmappableCharacterException; + +import sun.nio.cs.ISO_8859_1; import sun.security.action.GetPropertyAction; import sun.util.PropertyResourceBundleCharset; import sun.util.ResourceBundleEnumeration; @@ -176,7 +177,7 @@ public PropertyResourceBundle (InputStream stream) throws IOException { this(new InputStreamReader(stream, "ISO-8859-1".equals(encoding) ? - StandardCharsets.ISO_8859_1.newDecoder() : + ISO_8859_1.INSTANCE.newDecoder() : new PropertyResourceBundleCharset("UTF-8".equals(encoding)).newDecoder())); } diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -34,7 +34,6 @@ import java.io.UncheckedIOException; import java.lang.ref.Cleaner.Cleanable; import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.Files; @@ -66,6 +65,8 @@ import jdk.internal.ref.CleanerFactory; import jdk.internal.vm.annotation.Stable; +import sun.nio.cs.UTF_8; + import static java.util.zip.ZipConstants64.*; import static java.util.zip.ZipUtils.*; @@ -173,7 +174,7 @@ * @since 1.3 */ public ZipFile(File file, int mode) throws IOException { - this(file, mode, StandardCharsets.UTF_8); + this(file, mode, UTF_8.INSTANCE); } /** @@ -1094,7 +1095,7 @@ for (int i = 0; i < names.length; i++) { int pos = zsrc.metanames[i]; names[i] = new String(cen, pos + CENHDR, CENNAM(cen, pos), - StandardCharsets.UTF_8); + UTF_8.INSTANCE); } return names; } diff --git a/src/java.base/share/classes/java/util/zip/ZipInputStream.java b/src/java.base/share/classes/java/util/zip/ZipInputStream.java --- a/src/java.base/share/classes/java/util/zip/ZipInputStream.java +++ b/src/java.base/share/classes/java/util/zip/ZipInputStream.java @@ -30,10 +30,11 @@ import java.io.EOFException; import java.io.PushbackInputStream; import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import static java.util.zip.ZipConstants64.*; import static java.util.zip.ZipUtils.*; +import sun.nio.cs.UTF_8; + /** * This class implements an input stream filter for reading files in the * ZIP file format. Includes support for both compressed and uncompressed @@ -78,7 +79,7 @@ * @param in the actual input stream */ public ZipInputStream(InputStream in) { - this(in, StandardCharsets.UTF_8); + this(in, UTF_8.INSTANCE); } /** diff --git a/src/java.base/share/classes/java/util/zip/ZipOutputStream.java b/src/java.base/share/classes/java/util/zip/ZipOutputStream.java --- a/src/java.base/share/classes/java/util/zip/ZipOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/ZipOutputStream.java @@ -28,11 +28,12 @@ import java.io.OutputStream; import java.io.IOException; import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.util.Vector; import java.util.HashSet; import static java.util.zip.ZipConstants64.*; import static java.util.zip.ZipUtils.*; + +import sun.nio.cs.UTF_8; import sun.security.action.GetPropertyAction; /** @@ -116,7 +117,7 @@ * @param out the actual output stream */ public ZipOutputStream(OutputStream out) { - this(out, StandardCharsets.UTF_8); + this(out, UTF_8.INSTANCE); } /** diff --git a/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java b/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java --- a/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java +++ b/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java @@ -39,6 +39,8 @@ extends Charset implements HistoricallyNamedCharset { + public static final ISO_8859_1 INSTANCE = new ISO_8859_1(); + public ISO_8859_1() { super("ISO-8859-1", StandardCharsets.aliases_ISO_8859_1()); } diff --git a/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template b/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template --- a/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template +++ b/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template @@ -83,12 +83,12 @@ Map map = cache; if (map == null) { map = new Cache(); - map.put("utf-8", java.nio.charset.StandardCharsets.UTF_8); - map.put("iso-8859-1", java.nio.charset.StandardCharsets.ISO_8859_1); - map.put("us-ascii", java.nio.charset.StandardCharsets.US_ASCII); - map.put("utf-16", java.nio.charset.StandardCharsets.UTF_16); - map.put("utf-16be", java.nio.charset.StandardCharsets.UTF_16BE); - map.put("utf-16le", java.nio.charset.StandardCharsets.UTF_16LE); + map.put("utf-8", UTF_8.INSTANCE); + map.put("iso-8859-1", ISO_8859_1.INSTANCE); + map.put("us-ascii", US_ASCII.INSTANCE); + map.put("utf-16", UTF_16.INSTANCE); + map.put("utf-16be", UTF_16BE.INSTANCE); + map.put("utf-16le", UTF_16LE.INSTANCE); cache = map; } return map; @@ -122,15 +122,19 @@ private Charset lookup(String charsetName) { init(); - // By checking these built-ins we can avoid initializing Aliases and - // Classes eagerly during bootstrap + // By checking these built-ins we can avoid initializing Aliases, + // Classes and Cache eagerly during bootstrap. + // + // Initialization of java.nio.charset.StandardCharsets should be + // avoided here to minimize time spent in System.initPhase1, as it + // may delay initialization of performance critical VM subsystems. String csn; if (charsetName.equals("UTF-8")) { - return java.nio.charset.StandardCharsets.UTF_8; + return UTF_8.INSTANCE; } else if (charsetName.equals("US-ASCII")) { - return java.nio.charset.StandardCharsets.US_ASCII; + return US_ASCII.INSTANCE; } else if (charsetName.equals("ISO-8859-1")) { - return java.nio.charset.StandardCharsets.ISO_8859_1; + return ISO_8859_1.INSTANCE; } else { csn = canonicalize(toLower(charsetName)); } diff --git a/src/java.base/share/classes/sun/nio/cs/US_ASCII.java b/src/java.base/share/classes/sun/nio/cs/US_ASCII.java --- a/src/java.base/share/classes/sun/nio/cs/US_ASCII.java +++ b/src/java.base/share/classes/sun/nio/cs/US_ASCII.java @@ -36,6 +36,8 @@ extends Charset implements HistoricallyNamedCharset { + public static final US_ASCII INSTANCE = new US_ASCII(); + public US_ASCII() { super("US-ASCII", StandardCharsets.aliases_US_ASCII()); } diff --git a/src/java.base/share/classes/sun/nio/cs/UTF_16.java b/src/java.base/share/classes/sun/nio/cs/UTF_16.java --- a/src/java.base/share/classes/sun/nio/cs/UTF_16.java +++ b/src/java.base/share/classes/sun/nio/cs/UTF_16.java @@ -31,6 +31,7 @@ public class UTF_16 extends Unicode { + public static final UTF_16 INSTANCE = new UTF_16(); public UTF_16() { super("UTF-16", StandardCharsets.aliases_UTF_16()); diff --git a/src/java.base/share/classes/sun/nio/cs/UTF_16BE.java b/src/java.base/share/classes/sun/nio/cs/UTF_16BE.java --- a/src/java.base/share/classes/sun/nio/cs/UTF_16BE.java +++ b/src/java.base/share/classes/sun/nio/cs/UTF_16BE.java @@ -31,6 +31,7 @@ public class UTF_16BE extends Unicode { + public static final UTF_16BE INSTANCE = new UTF_16BE(); public UTF_16BE() { super("UTF-16BE", StandardCharsets.aliases_UTF_16BE()); diff --git a/src/java.base/share/classes/sun/nio/cs/UTF_16LE.java b/src/java.base/share/classes/sun/nio/cs/UTF_16LE.java --- a/src/java.base/share/classes/sun/nio/cs/UTF_16LE.java +++ b/src/java.base/share/classes/sun/nio/cs/UTF_16LE.java @@ -31,6 +31,7 @@ public class UTF_16LE extends Unicode { + public static final UTF_16LE INSTANCE = new UTF_16LE(); public UTF_16LE() { super("UTF-16LE", StandardCharsets.aliases_UTF_16LE()); diff --git a/src/java.base/share/classes/sun/nio/cs/UTF_8.java b/src/java.base/share/classes/sun/nio/cs/UTF_8.java --- a/src/java.base/share/classes/sun/nio/cs/UTF_8.java +++ b/src/java.base/share/classes/sun/nio/cs/UTF_8.java @@ -55,6 +55,9 @@ */ public final class UTF_8 extends Unicode { + + public static final UTF_8 INSTANCE = new UTF_8(); + public UTF_8() { super("UTF-8", StandardCharsets.aliases_UTF_8()); } diff --git a/src/java.base/share/classes/sun/util/PropertyResourceBundleCharset.java b/src/java.base/share/classes/sun/util/PropertyResourceBundleCharset.java --- a/src/java.base/share/classes/sun/util/PropertyResourceBundleCharset.java +++ b/src/java.base/share/classes/sun/util/PropertyResourceBundleCharset.java @@ -32,9 +32,11 @@ import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; -import java.nio.charset.StandardCharsets; import java.util.Objects; +import sun.nio.cs.ISO_8859_1; +import sun.nio.cs.UTF_8; + /** * A Charset implementation for reading PropertyResourceBundle, in order * for loading properties files. This first tries to load the properties @@ -70,7 +72,7 @@ private final class PropertiesFileDecoder extends CharsetDecoder { - private CharsetDecoder cdUTF_8 = StandardCharsets.UTF_8.newDecoder() + private CharsetDecoder cdUTF_8 = UTF_8.INSTANCE.newDecoder() .onMalformedInput(CodingErrorAction.REPORT) .onUnmappableCharacter(CodingErrorAction.REPORT); private CharsetDecoder cdISO_8859_1 = null; @@ -98,7 +100,7 @@ assert cr.isMalformed() || cr.isUnmappable(); in.reset(); out.reset(); - cdISO_8859_1 = StandardCharsets.ISO_8859_1.newDecoder(); + cdISO_8859_1 = ISO_8859_1.INSTANCE.newDecoder(); return cdISO_8859_1.decode(in, out, false); } }