7133138: Improve io performance around timezone lookups
Reviewed-by: okutsu
diff --git a/jdk/make/tools/src/build/tools/javazic/Mappings.java b/jdk/make/tools/src/build/tools/javazic/Mappings.java
index 5e5498a..885b9a0 100644
--- a/jdk/make/tools/src/build/tools/javazic/Mappings.java
+++ b/jdk/make/tools/src/build/tools/javazic/Mappings.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -26,6 +26,7 @@
package build.tools.javazic;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -162,6 +163,20 @@
for (String key : toBeRemoved) {
aliases.remove(key);
}
+ // Eliminate any alias-to-alias mappings. For example, if
+ // there are A->B and B->C, A->B is changed to A->C.
+ Map<String, String> newMap = new HashMap<String, String>();
+ for (String key : aliases.keySet()) {
+ String realid = aliases.get(key);
+ String leaf = realid;
+ while (aliases.get(leaf) != null) {
+ leaf = aliases.get(leaf);
+ }
+ if (!realid.equals(leaf)) {
+ newMap.put(key, leaf);
+ }
+ }
+ aliases.putAll(newMap);
}
Map<String,String> getAliases() {
diff --git a/jdk/src/share/classes/sun/util/calendar/ZoneInfo.java b/jdk/src/share/classes/sun/util/calendar/ZoneInfo.java
index b79e7cc..339c045 100644
--- a/jdk/src/share/classes/sun/util/calendar/ZoneInfo.java
+++ b/jdk/src/share/classes/sun/util/calendar/ZoneInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -80,13 +80,18 @@
private static final int TRANSITION_NSHIFT = 12;
// Flag for supporting JDK backward compatible IDs, such as "EST".
- private static final boolean USE_OLDMAPPING;
+ static final boolean USE_OLDMAPPING;
static {
String oldmapping = AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("sun.timezone.ids.oldmapping", "false")).toLowerCase(Locale.ROOT);
USE_OLDMAPPING = (oldmapping.equals("yes") || oldmapping.equals("true"));
}
+ // IDs having conflicting data between Olson and JDK 1.1
+ static final String[] conflictingIDs = {
+ "EST", "MST", "HST"
+ };
+
private static final CalendarSystem gcal = CalendarSystem.getGregorianCalendar();
/**
@@ -807,7 +812,17 @@
return (checksum == ((ZoneInfo)other).checksum);
}
- private static SoftReference<Map> aliasTable;
+ private static SoftReference<Map<String, String>> aliasTable;
+
+ static Map<String, String> getCachedAliasTable() {
+ Map<String, String> aliases = null;
+
+ SoftReference<Map<String, String>> cache = aliasTable;
+ if (cache != null) {
+ aliases = cache.get();
+ }
+ return aliases;
+ }
/**
* Returns a Map from alias time zone IDs to their standard
@@ -818,20 +833,19 @@
* <code>ZoneInfoMappings</code> file is not available.
*/
public synchronized static Map<String, String> getAliasTable() {
- Map<String, String> aliases = null;
-
- SoftReference<Map> cache = aliasTable;
- if (cache != null) {
- aliases = cache.get();
+ Map<String, String> aliases = getCachedAliasTable();
+ if (aliases == null) {
+ aliases = ZoneInfoFile.getZoneAliases();
if (aliases != null) {
- return aliases;
+ if (!USE_OLDMAPPING) {
+ // Remove the conflicting IDs from the alias table.
+ for (String key : conflictingIDs) {
+ aliases.remove(key);
+ }
+ }
+ aliasTable = new SoftReference<Map<String, String>>(aliases);
}
}
-
- aliases = ZoneInfoFile.getZoneAliases();
- if (aliases != null) {
- aliasTable = new SoftReference<Map>(aliases);
- }
return aliases;
}
diff --git a/jdk/src/share/classes/sun/util/calendar/ZoneInfoFile.java b/jdk/src/share/classes/sun/util/calendar/ZoneInfoFile.java
index 8918177..7fdc85c 100644
--- a/jdk/src/share/classes/sun/util/calendar/ZoneInfoFile.java
+++ b/jdk/src/share/classes/sun/util/calendar/ZoneInfoFile.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -472,6 +472,7 @@
public static final byte TAG_ExcludedZones = 69;
private static Map<String, ZoneInfo> zoneInfoObjects = null;
+ private static final ZoneInfo GMT = new ZoneInfo("GMT", 0);
private static final String ziDir = AccessController.doPrivileged(
new PrivilegedAction<String>() {
@@ -553,8 +554,15 @@
* id.
*/
public static ZoneInfo getZoneInfo(String id) {
+ //treat GMT zone as special
+ if ("GMT".equals(id))
+ return (ZoneInfo) GMT.clone();
ZoneInfo zi = getFromCache(id);
if (zi == null) {
+ Map<String, String> aliases = ZoneInfo.getCachedAliasTable();
+ if (aliases != null && aliases.get(id) != null) {
+ return null;
+ }
zi = createZoneInfo(id);
if (zi == null) {
return null;
@@ -1031,30 +1039,26 @@
* @return the buffer, or null if any I/O error occurred.
*/
private static byte[] readZoneInfoFile(final String fileName) {
+ if (fileName.indexOf("..") >= 0) {
+ return null;
+ }
byte[] buffer = null;
try {
buffer = (byte[]) AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws IOException {
File file = new File(ziDir, fileName);
- if (!file.exists() || !file.isFile()) {
- return null;
- }
- file = file.getCanonicalFile();
- String path = file.getCanonicalPath();
byte[] buf = null;
- if (path != null && path.startsWith(ziDir)) {
- int filesize = (int)file.length();
- if (filesize > 0) {
- FileInputStream fis = new FileInputStream(file);
- buf = new byte[filesize];
- try {
- if (fis.read(buf) != filesize) {
- throw new IOException("read error on " + fileName);
- }
- } finally {
- fis.close();
+ int filesize = (int)file.length();
+ if (filesize > 0) {
+ FileInputStream fis = new FileInputStream(file);
+ buf = new byte[filesize];
+ try {
+ if (fis.read(buf) != filesize) {
+ throw new IOException("read error on " + fileName);
}
+ } finally {
+ fis.close();
}
}
return buf;