--- old/src/java.base/share/classes/java/time/ZoneId.java 2015-02-22 20:39:44.555107230 +0100 +++ new/src/java.base/share/classes/java/time/ZoneId.java 2015-02-22 20:39:44.456108970 +0100 @@ -61,6 +61,8 @@ */ package java.time; +import sun.misc.SharedSecrets; + import java.io.DataOutput; import java.io.IOException; import java.io.InvalidObjectException; @@ -271,7 +273,7 @@ * @throws ZoneRulesException if the converted zone region ID cannot be found */ public static ZoneId systemDefault() { - return TimeZone.getDefault().toZoneId(); + return SharedSecrets.getJavaUtilTimeZoneAccess().getDefaultRef().toZoneId(); } /** --- old/src/java.base/share/classes/java/util/TimeZone.java 2015-02-22 20:39:44.871101675 +0100 +++ new/src/java.base/share/classes/java/util/TimeZone.java 2015-02-22 20:39:44.742103943 +0100 @@ -42,6 +42,9 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.time.ZoneId; + +import sun.misc.JavaUtilTimeZoneAccess; +import sun.misc.SharedSecrets; import sun.security.action.GetPropertyAction; import sun.util.calendar.ZoneInfo; import sun.util.calendar.ZoneInfoFile; @@ -131,6 +134,16 @@ * @since 1.1 */ abstract public class TimeZone implements Serializable, Cloneable { + + static { + SharedSecrets.setJavaUtilTimeZoneAccess(new JavaUtilTimeZoneAccess() { + @Override + public TimeZone getDefaultRef() { + return TimeZone.getDefaultRef(); + } + }); + } + /** * Sole constructor. (For invocation by subclass constructors, typically * implicit.) @@ -293,6 +306,7 @@ throw new NullPointerException(); } this.ID = ID; + this.zoneId = null; // invalidate cache } /** @@ -544,16 +558,22 @@ * @since 1.8 */ public ZoneId toZoneId() { - String id = getID(); - if (ZoneInfoFile.useOldMapping() && id.length() == 3) { - if ("EST".equals(id)) - return ZoneId.of("America/New_York"); - if ("MST".equals(id)) - return ZoneId.of("America/Denver"); - if ("HST".equals(id)) - return ZoneId.of("America/Honolulu"); + ZoneId zId = zoneId; + if (zId == null) { + String id = getID(); + if (ZoneInfoFile.useOldMapping() && id.length() == 3) { + if ("EST".equals(id)) + zId = ZoneId.of("America/New_York"); + else if ("MST".equals(id)) + zId = ZoneId.of("America/Denver"); + else if ("HST".equals(id)) + zId = ZoneId.of("America/Honolulu"); + } else { + zId = ZoneId.of(id, ZoneId.SHORT_IDS); + } + zoneId = zId; } - return ZoneId.of(id, ZoneId.SHORT_IDS); + return zId; } private static TimeZone getTimeZone(String ID, boolean fallback) { @@ -710,7 +730,7 @@ sm.checkPermission(new PropertyPermission ("user.timezone", "write")); } - defaultTimeZone = zone; + defaultTimeZone = (TimeZone) zone.clone(); } /** @@ -735,9 +755,7 @@ public Object clone() { try { - TimeZone other = (TimeZone) super.clone(); - other.ID = ID; - return other; + return super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(e); } @@ -759,6 +777,12 @@ * @serial */ private String ID; + + /** + * Cached {@link ZoneId} for this TimeZone + */ + private transient ZoneId zoneId; + private static volatile TimeZone defaultTimeZone; static final String GMT_ID = "GMT"; --- old/src/java.base/share/classes/sun/misc/SharedSecrets.java 2015-02-22 20:39:45.181096227 +0100 +++ new/src/java.base/share/classes/sun/misc/SharedSecrets.java 2015-02-22 20:39:45.066098248 +0100 @@ -53,6 +53,7 @@ private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess; private static JavaSecurityProtectionDomainAccess javaSecurityProtectionDomainAccess; private static JavaSecurityAccess javaSecurityAccess; + private static JavaUtilTimeZoneAccess javaUtilTimeZoneAccess; private static JavaUtilZipFileAccess javaUtilZipFileAccess; private static JavaAWTAccess javaAWTAccess; private static JavaAWTFontAccess javaAWTFontAccess; @@ -164,6 +165,16 @@ return javaSecurityAccess; } + public static JavaUtilTimeZoneAccess getJavaUtilTimeZoneAccess() { + if (javaUtilTimeZoneAccess == null) + unsafe.ensureClassInitialized(java.util.TimeZone.class); + return javaUtilTimeZoneAccess; + } + + public static void setJavaUtilTimeZoneAccess(JavaUtilTimeZoneAccess access) { + javaUtilTimeZoneAccess = access; + } + public static JavaUtilZipFileAccess getJavaUtilZipFileAccess() { if (javaUtilZipFileAccess == null) unsafe.ensureClassInitialized(java.util.zip.ZipFile.class); --- /dev/null 2015-02-22 16:29:22.615854330 +0100 +++ new/src/java.base/share/classes/sun/misc/JavaUtilTimeZoneAccess.java 2015-02-22 20:39:45.375092817 +0100 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.misc; + +import java.util.TimeZone; + +public interface JavaUtilTimeZoneAccess { + public TimeZone getDefaultRef(); +} +