7200341: DateFormatSymbols.hashCode() throws ArrayIndexOutOfBoundsException in some circumstances
Reviewed-by: okutsu
--- a/jdk/src/share/classes/java/text/DateFormatSymbols.java Tue Oct 09 08:58:27 2012 -0400
+++ b/jdk/src/share/classes/java/text/DateFormatSymbols.java Tue Oct 09 09:59:05 2012 -0700
@@ -45,6 +45,7 @@
import java.text.spi.DateFormatSymbolsProvider;
import java.util.Arrays;
import java.util.Locale;
+import java.util.Objects;
import java.util.ResourceBundle;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
@@ -366,6 +367,7 @@
*/
public void setEras(String[] newEras) {
eras = Arrays.copyOf(newEras, newEras.length);
+ cachedHashCode = 0;
}
/**
@@ -393,6 +395,7 @@
*/
public void setMonths(String[] newMonths) {
months = Arrays.copyOf(newMonths, newMonths.length);
+ cachedHashCode = 0;
}
/**
@@ -420,6 +423,7 @@
*/
public void setShortMonths(String[] newShortMonths) {
shortMonths = Arrays.copyOf(newShortMonths, newShortMonths.length);
+ cachedHashCode = 0;
}
/**
@@ -439,6 +443,7 @@
*/
public void setWeekdays(String[] newWeekdays) {
weekdays = Arrays.copyOf(newWeekdays, newWeekdays.length);
+ cachedHashCode = 0;
}
/**
@@ -458,6 +463,7 @@
*/
public void setShortWeekdays(String[] newShortWeekdays) {
shortWeekdays = Arrays.copyOf(newShortWeekdays, newShortWeekdays.length);
+ cachedHashCode = 0;
}
/**
@@ -474,6 +480,7 @@
*/
public void setAmPmStrings(String[] newAmpms) {
ampms = Arrays.copyOf(newAmpms, newAmpms.length);
+ cachedHashCode = 0;
}
/**
@@ -558,6 +565,7 @@
}
zoneStrings = aCopy;
isZoneStringsSet = true;
+ cachedHashCode = 0;
}
/**
@@ -576,6 +584,7 @@
public void setLocalPatternChars(String newLocalPatternChars) {
// Call toString() to throw an NPE in case the argument is null
localPatternChars = newLocalPatternChars.toString();
+ cachedHashCode = 0;
}
/**
@@ -597,12 +606,23 @@
* Override hashCode.
* Generates a hash code for the DateFormatSymbols object.
*/
+ @Override
public int hashCode() {
- int hashcode = 0;
- String[][] zoneStrings = getZoneStringsWrapper();
- for (int index = 0; index < zoneStrings[0].length; ++index)
- hashcode ^= zoneStrings[0][index].hashCode();
- return hashcode;
+ int hashCode = cachedHashCode;
+ if (hashCode == 0) {
+ hashCode = 5;
+ hashCode = 11 * hashCode + Arrays.hashCode(eras);
+ hashCode = 11 * hashCode + Arrays.hashCode(months);
+ hashCode = 11 * hashCode + Arrays.hashCode(shortMonths);
+ hashCode = 11 * hashCode + Arrays.hashCode(weekdays);
+ hashCode = 11 * hashCode + Arrays.hashCode(shortWeekdays);
+ hashCode = 11 * hashCode + Arrays.hashCode(ampms);
+ hashCode = 11 * hashCode + Arrays.deepHashCode(getZoneStringsWrapper());
+ hashCode = 11 * hashCode + Objects.hashCode(localPatternChars);
+ cachedHashCode = hashCode;
+ }
+
+ return hashCode;
}
/**
@@ -641,6 +661,11 @@
private transient int lastZoneIndex = 0;
+ /**
+ * Cached hash code
+ */
+ transient volatile int cachedHashCode = 0;
+
private void initializeData(Locale desiredLocale) {
locale = desiredLocale;
@@ -782,6 +807,7 @@
dst.zoneStrings = null;
}
dst.localPatternChars = src.localPatternChars;
+ dst.cachedHashCode = 0;
}
/**
--- a/jdk/test/java/util/PluggableLocale/DateFormatSymbolsProviderTest.java Tue Oct 09 08:58:27 2012 -0400
+++ b/jdk/test/java/util/PluggableLocale/DateFormatSymbolsProviderTest.java Tue Oct 09 09:59:05 2012 -0700
@@ -44,6 +44,7 @@
DateFormatSymbolsProviderTest() {
availableLocalesTest();
objectValidityTest();
+ hashCodeTest();
}
void availableLocalesTest() {
@@ -124,4 +125,17 @@
}
}
}
+
+ // Bug 7200341.
+ void hashCodeTest() {
+ for (Locale target: availloc) {
+ // look for provider's object
+ DateFormatSymbols dfs = DateFormatSymbols.getInstance(target);
+ if (dfs.getClass().getSimpleName().equals("FooDateFormatSymbols")) {
+ // call its hashCode(). success if no ArrayIndexOutOfBoundsException is thrown.
+ dfs.hashCode();
+ break;
+ }
+ }
+ }
}
--- a/jdk/test/java/util/PluggableLocale/DateFormatSymbolsProviderTest.sh Tue Oct 09 08:58:27 2012 -0400
+++ b/jdk/test/java/util/PluggableLocale/DateFormatSymbolsProviderTest.sh Tue Oct 09 09:59:05 2012 -0700
@@ -23,6 +23,6 @@
#!/bin/sh
#
# @test
-# @bug 4052440
+# @bug 4052440 7200341
# @summary DateFormatSymbolsProvider tests
# @run shell ExecTest.sh foo DateFormatSymbolsProviderTest true
Binary file jdk/test/java/util/PluggableLocale/fooprovider.jar has changed
--- a/jdk/test/java/util/PluggableLocale/providersrc/DateFormatSymbolsProviderImpl.java Tue Oct 09 08:58:27 2012 -0400
+++ b/jdk/test/java/util/PluggableLocale/providersrc/DateFormatSymbolsProviderImpl.java Tue Oct 09 09:59:05 2012 -0700
@@ -221,5 +221,10 @@
public void setAmPmStrings(String[] newAmpms) {
ampms = newAmpms;
}
+
+ @Override
+ public String[][] getZoneStrings() {
+ return new String[0][0];
+ }
}
}