This commit is contained in:
Alan Bateman 2011-04-06 20:54:12 +01:00
commit ddc9107b92
9 changed files with 570 additions and 111 deletions

View File

@ -106,7 +106,7 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
/** /**
* Distinguished non-null value for representing null values. * Distinguished non-null value for representing null values.
*/ */
private static final Object NULL = new Object(); private static final Object NULL = new Integer(0);
private Object maskNull(Object value) { private Object maskNull(Object value) {
return (value == null ? NULL : value); return (value == null ? NULL : value);
@ -116,7 +116,7 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
return (V) (value == NULL ? null : value); return (V) (value == NULL ? null : value);
} }
private static Enum[] ZERO_LENGTH_ENUM_ARRAY = new Enum[0]; private static final Enum[] ZERO_LENGTH_ENUM_ARRAY = new Enum[0];
/** /**
* Creates an empty enum map with the specified key type. * Creates an empty enum map with the specified key type.
@ -464,6 +464,7 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
public Iterator<Map.Entry<K,V>> iterator() { public Iterator<Map.Entry<K,V>> iterator() {
return new EntryIterator(); return new EntryIterator();
} }
public boolean contains(Object o) { public boolean contains(Object o) {
if (!(o instanceof Map.Entry)) if (!(o instanceof Map.Entry))
return false; return false;
@ -552,70 +553,82 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
} }
} }
/** private class EntryIterator extends EnumMapIterator<Map.Entry<K,V>> {
* Since we don't use Entry objects, we use the Iterator itself as entry. private Entry lastReturnedEntry = null;
*/
private class EntryIterator extends EnumMapIterator<Map.Entry<K,V>>
implements Map.Entry<K,V>
{
public Map.Entry<K,V> next() { public Map.Entry<K,V> next() {
if (!hasNext()) if (!hasNext())
throw new NoSuchElementException(); throw new NoSuchElementException();
lastReturnedIndex = index++; lastReturnedEntry = new Entry(index++);
return this; return lastReturnedEntry;
} }
public K getKey() { public void remove() {
checkLastReturnedIndexForEntryUse(); lastReturnedIndex =
return keyUniverse[lastReturnedIndex]; ((null == lastReturnedEntry) ? -1 : lastReturnedEntry.index);
super.remove();
lastReturnedEntry.index = lastReturnedIndex;
lastReturnedEntry = null;
} }
public V getValue() { private class Entry implements Map.Entry<K,V> {
checkLastReturnedIndexForEntryUse(); private int index;
return unmaskNull(vals[lastReturnedIndex]);
}
public V setValue(V value) { private Entry(int index) {
checkLastReturnedIndexForEntryUse(); this.index = index;
V oldValue = unmaskNull(vals[lastReturnedIndex]); }
vals[lastReturnedIndex] = maskNull(value);
return oldValue;
}
public boolean equals(Object o) { public K getKey() {
if (lastReturnedIndex < 0) checkIndexForEntryUse();
return o == this; return keyUniverse[index];
}
if (!(o instanceof Map.Entry)) public V getValue() {
return false; checkIndexForEntryUse();
Map.Entry e = (Map.Entry)o; return unmaskNull(vals[index]);
V ourValue = unmaskNull(vals[lastReturnedIndex]); }
Object hisValue = e.getValue();
return e.getKey() == keyUniverse[lastReturnedIndex] &&
(ourValue == hisValue ||
(ourValue != null && ourValue.equals(hisValue)));
}
public int hashCode() { public V setValue(V value) {
if (lastReturnedIndex < 0) checkIndexForEntryUse();
return super.hashCode(); V oldValue = unmaskNull(vals[index]);
vals[index] = maskNull(value);
return oldValue;
}
Object value = vals[lastReturnedIndex]; public boolean equals(Object o) {
return keyUniverse[lastReturnedIndex].hashCode() if (index < 0)
^ (value == NULL ? 0 : value.hashCode()); return o == this;
}
public String toString() { if (!(o instanceof Map.Entry))
if (lastReturnedIndex < 0) return false;
return super.toString();
return keyUniverse[lastReturnedIndex] + "=" Map.Entry e = (Map.Entry)o;
+ unmaskNull(vals[lastReturnedIndex]); V ourValue = unmaskNull(vals[index]);
} Object hisValue = e.getValue();
return (e.getKey() == keyUniverse[index] &&
(ourValue == hisValue ||
(ourValue != null && ourValue.equals(hisValue))));
}
private void checkLastReturnedIndexForEntryUse() { public int hashCode() {
if (lastReturnedIndex < 0) if (index < 0)
throw new IllegalStateException("Entry was removed"); return super.hashCode();
return entryHashCode(index);
}
public String toString() {
if (index < 0)
return super.toString();
return keyUniverse[index] + "="
+ unmaskNull(vals[index]);
}
private void checkIndexForEntryUse() {
if (index < 0)
throw new IllegalStateException("Entry was removed");
}
} }
} }
@ -631,10 +644,35 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
* @return <tt>true</tt> if the specified object is equal to this map * @return <tt>true</tt> if the specified object is equal to this map
*/ */
public boolean equals(Object o) { public boolean equals(Object o) {
if (!(o instanceof EnumMap)) if (this == o)
return super.equals(o); return true;
if (o instanceof EnumMap)
return equals((EnumMap)o);
if (!(o instanceof Map))
return false;
EnumMap em = (EnumMap)o; Map<K,V> m = (Map<K,V>)o;
if (size != m.size())
return false;
for (int i = 0; i < keyUniverse.length; i++) {
if (null != vals[i]) {
K key = keyUniverse[i];
V value = unmaskNull(vals[i]);
if (null == value) {
if (!((null == m.get(key)) && m.containsKey(key)))
return false;
} else {
if (!value.equals(m.get(key)))
return false;
}
}
}
return true;
}
private boolean equals(EnumMap em) {
if (em.keyType != keyType) if (em.keyType != keyType)
return size == 0 && em.size == 0; return size == 0 && em.size == 0;
@ -649,6 +687,26 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
return true; return true;
} }
/**
* Returns the hash code value for this map. The hash code of a map is
* defined to be the sum of the hash codes of each entry in the map.
*/
public int hashCode() {
int h = 0;
for (int i = 0; i < keyUniverse.length; i++) {
if (null != vals[i]) {
h += entryHashCode(i);
}
}
return h;
}
private int entryHashCode(int index) {
return (keyUniverse[index].hashCode() ^ vals[index].hashCode());
}
/** /**
* Returns a shallow copy of this enum map. (The values themselves * Returns a shallow copy of this enum map. (The values themselves
* are not cloned. * are not cloned.
@ -705,9 +763,13 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
s.writeInt(size); s.writeInt(size);
// Write out keys and values (alternating) // Write out keys and values (alternating)
for (Map.Entry<K,V> e : entrySet()) { int entriesToBeWritten = size;
s.writeObject(e.getKey()); for (int i = 0; entriesToBeWritten > 0; i++) {
s.writeObject(e.getValue()); if (null != vals[i]) {
s.writeObject(keyUniverse[i]);
s.writeObject(unmaskNull(vals[i]));
entriesToBeWritten--;
}
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -829,71 +829,82 @@ public class IdentityHashMap<K,V>
} }
} }
/**
* Since we don't use Entry objects, we use the Iterator
* itself as an entry.
*/
private class EntryIterator private class EntryIterator
extends IdentityHashMapIterator<Map.Entry<K,V>> extends IdentityHashMapIterator<Map.Entry<K,V>>
implements Map.Entry<K,V>
{ {
private Entry lastReturnedEntry = null;
public Map.Entry<K,V> next() { public Map.Entry<K,V> next() {
nextIndex(); lastReturnedEntry = new Entry(nextIndex());
return this; return lastReturnedEntry;
} }
public K getKey() { public void remove() {
// Provide a better exception than out of bounds index lastReturnedIndex =
if (lastReturnedIndex < 0) ((null == lastReturnedEntry) ? -1 : lastReturnedEntry.index);
throw new IllegalStateException("Entry was removed"); super.remove();
lastReturnedEntry.index = lastReturnedIndex;
return (K) unmaskNull(traversalTable[lastReturnedIndex]); lastReturnedEntry = null;
} }
public V getValue() { private class Entry implements Map.Entry<K,V> {
// Provide a better exception than out of bounds index private int index;
if (lastReturnedIndex < 0)
throw new IllegalStateException("Entry was removed");
return (V) traversalTable[lastReturnedIndex+1]; private Entry(int index) {
} this.index = index;
}
public V setValue(V value) { public K getKey() {
// It would be mean-spirited to proceed here if remove() called checkIndexForEntryUse();
if (lastReturnedIndex < 0) return (K) unmaskNull(traversalTable[index]);
throw new IllegalStateException("Entry was removed"); }
V oldValue = (V) traversalTable[lastReturnedIndex+1];
traversalTable[lastReturnedIndex+1] = value;
// if shadowing, force into main table
if (traversalTable != IdentityHashMap.this.table)
put((K) traversalTable[lastReturnedIndex], value);
return oldValue;
}
public boolean equals(Object o) { public V getValue() {
if (lastReturnedIndex < 0) checkIndexForEntryUse();
return super.equals(o); return (V) traversalTable[index+1];
}
if (!(o instanceof Map.Entry)) public V setValue(V value) {
return false; checkIndexForEntryUse();
Map.Entry e = (Map.Entry)o; V oldValue = (V) traversalTable[index+1];
return e.getKey() == getKey() && traversalTable[index+1] = value;
e.getValue() == getValue(); // if shadowing, force into main table
} if (traversalTable != IdentityHashMap.this.table)
put((K) traversalTable[index], value);
return oldValue;
}
public int hashCode() { public boolean equals(Object o) {
if (lastReturnedIndex < 0) if (index < 0)
return super.hashCode(); return super.equals(o);
return System.identityHashCode(getKey()) ^ if (!(o instanceof Map.Entry))
System.identityHashCode(getValue()); return false;
} Map.Entry e = (Map.Entry)o;
return (e.getKey() == unmaskNull(traversalTable[index]) &&
e.getValue() == traversalTable[index+1]);
}
public String toString() { public int hashCode() {
if (lastReturnedIndex < 0) if (lastReturnedIndex < 0)
return super.toString(); return super.hashCode();
return getKey() + "=" + getValue(); return (System.identityHashCode(unmaskNull(traversalTable[index])) ^
System.identityHashCode(traversalTable[index+1]));
}
public String toString() {
if (index < 0)
return super.toString();
return (unmaskNull(traversalTable[index]) + "="
+ traversalTable[index+1]);
}
private void checkIndexForEntryUse() {
if (index < 0)
throw new IllegalStateException("Entry was removed");
}
} }
} }

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2011 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.
*
* 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.
*/
/*
* Portions Copyright (c) 2011 IBM Corporation
*/
/*
* @test
* @bug 6312706
* @summary Sets from Map.entrySet() return distinct objects for each Entry
* @author Neil Richards <neil.richards@ngmr.net>, <neil_richards@uk.ibm.com>
*/
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class DistinctEntrySetElements {
static enum TestEnum { e00, e01, e02 }
public static void main(String[] args) throws Exception {
final EnumMap<TestEnum, String> enumMap = new EnumMap<>(TestEnum.class);
for (TestEnum e : TestEnum.values()) {
enumMap.put(e, e.name());
}
Set<Map.Entry<TestEnum, String>> entrySet = enumMap.entrySet();
HashSet<Map.Entry<TestEnum, String>> hashSet = new HashSet<>(entrySet);
if (false == hashSet.equals(entrySet)) {
throw new RuntimeException("Test FAILED: Sets are not equal.");
}
if (hashSet.hashCode() != entrySet.hashCode()) {
throw new RuntimeException("Test FAILED: Set's hashcodes are not equal.");
}
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2011 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.
*
* 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.
*/
/*
* Portions Copyright (c) 2011 IBM Corporation
*/
/*
* @test
* @bug 6312706
* @summary Iterator.remove() from Map.entrySet().iterator() invalidates returned Entry.
* @author Neil Richards <neil.richards@ngmr.net>, <neil_richards@uk.ibm.com>
*/
import java.util.EnumMap;
import java.util.Iterator;
import java.util.Map;
public class EntrySetIteratorRemoveInvalidatesEntry {
static enum TestEnum { e00, e01, e02 }
public static void main(String[] args) throws Exception {
final EnumMap<TestEnum, String> enumMap = new EnumMap<>(TestEnum.class);
for (TestEnum e : TestEnum.values()) {
enumMap.put(e, e.name());
}
Iterator<Map.Entry<TestEnum, String>> entrySetIterator =
enumMap.entrySet().iterator();
Map.Entry<TestEnum, String> entry = entrySetIterator.next();
entrySetIterator.remove();
try {
entry.getKey();
throw new RuntimeException("Test FAILED: Entry not invalidated by removal.");
} catch (Exception e) { }
}
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2011 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.
*
* 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.
*/
/*
* Portions Copyright (c) 2011 IBM Corporation
*/
/*
* @test
* @bug 6312706
* @summary A serialized EnumMap can be successfully de-serialized.
* @author Neil Richards <neil.richards@ngmr.net>, <neil_richards@uk.ibm.com>
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.EnumMap;
public class SimpleSerialization {
private enum TestEnum { e00, e01, e02, e03, e04, e05, e06, e07 }
public static void main(final String[] args) throws Exception {
final EnumMap<TestEnum, String> enumMap = new EnumMap<>(TestEnum.class);
enumMap.put(TestEnum.e01, TestEnum.e01.name());
enumMap.put(TestEnum.e04, TestEnum.e04.name());
enumMap.put(TestEnum.e05, TestEnum.e05.name());
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(enumMap);
oos.close();
final byte[] data = baos.toByteArray();
final ByteArrayInputStream bais = new ByteArrayInputStream(data);
final ObjectInputStream ois = new ObjectInputStream(bais);
final Object deserializedObject = ois.readObject();
ois.close();
if (false == enumMap.equals(deserializedObject)) {
throw new RuntimeException(getFailureText(enumMap, deserializedObject));
}
}
private static String getFailureText(final Object orig, final Object copy) {
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw);
pw.println("Test FAILED: Deserialized object is not equal to the original object");
pw.print("\tOriginal: ");
printObject(pw, orig).println();
pw.print("\tCopy: ");
printObject(pw, copy).println();
pw.close();
return sw.toString();
}
private static PrintWriter printObject(final PrintWriter pw, final Object o) {
pw.printf("%s@%08x", o.getClass().getName(), System.identityHashCode(o));
return pw;
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2011 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.
*
* 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.
*/
/*
* Portions Copyright (c) 2011 IBM Corporation
*/
/*
* @test
* @bug 6312706
* @summary Sets from Map.entrySet() return distinct objects for each Entry
* @author Neil Richards <neil.richards@ngmr.net>, <neil_richards@uk.ibm.com>
*/
import java.util.IdentityHashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class DistinctEntrySetElements {
public static void main(String[] args) throws Exception {
final IdentityHashMap<String, String> identityHashMap =
new IdentityHashMap<>();
identityHashMap.put("One", "Un");
identityHashMap.put("Two", "Deux");
identityHashMap.put("Three", "Trois");
Set<Map.Entry<String, String>> entrySet = identityHashMap.entrySet();
HashSet<Map.Entry<String, String>> hashSet = new HashSet<>(entrySet);
// NB: These comparisons are valid in this case because none of the
// keys put into 'identityHashMap' above are equal to any other.
if (false == hashSet.equals(entrySet)) {
throw new RuntimeException("Test FAILED: Sets are not equal.");
}
if (hashSet.hashCode() != entrySet.hashCode()) {
throw new RuntimeException("Test FAILED: Set's hashcodes are not equal.");
}
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2011 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.
*
* 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.
*/
/*
* Portions Copyright (c) 2011 IBM Corporation
*/
/*
* @test
* @bug 6312706
* @summary Iterator.remove() from Map.entrySet().iterator() invalidates returned Entry.
* @author Neil Richards <neil.richards@ngmr.net>, <neil_richards@uk.ibm.com>
*/
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
public class EntrySetIteratorRemoveInvalidatesEntry {
public static void main(String[] args) throws Exception {
final IdentityHashMap<String, String> identityHashMap =
new IdentityHashMap<>();
identityHashMap.put("One", "Un");
identityHashMap.put("Two", "Deux");
identityHashMap.put("Three", "Trois");
Iterator<Map.Entry<String, String>> entrySetIterator =
identityHashMap.entrySet().iterator();
Map.Entry<String, String> entry = entrySetIterator.next();
entrySetIterator.remove();
try {
entry.getKey();
throw new RuntimeException("Test FAILED: Entry not invalidated by removal.");
} catch (Exception e) { }
}
}

View File

@ -282,7 +282,7 @@ public class Bug4168625Test extends RBTestFmwk {
thread1.start(); //start thread 1 thread1.start(); //start thread 1
loader.waitForNotify(1); //wait for thread1 to do getBundle & block in loader loader.waitForNotify(1); //wait for thread1 to do getBundle & block in loader
thread2.start(); //start second thread thread2.start(); //start second thread
thread2.join(1000); //wait until thread2 blocks somewhere in getBundle thread2.join(); //wait until thread2 terminates.
//Thread1 should be blocked inside getBundle at the class loader //Thread1 should be blocked inside getBundle at the class loader
//Thread2 should have completed its getBundle call and terminated //Thread2 should have completed its getBundle call and terminated
@ -292,7 +292,6 @@ public class Bug4168625Test extends RBTestFmwk {
thread1.ping(); //continue thread1 thread1.ping(); //continue thread1
thread1.join(); thread1.join();
thread2.join();
} }
/** /**
@ -318,8 +317,7 @@ public class Bug4168625Test extends RBTestFmwk {
loader.waitForNotify(3); //wait for thread1 to do getBundle(en) & block in loader loader.waitForNotify(3); //wait for thread1 to do getBundle(en) & block in loader
causeResourceBundleCacheFlush(); //cause a cache flush causeResourceBundleCacheFlush(); //cause a cache flush
thread1.ping(); //kick thread 1 thread1.ping(); //kick thread 1
thread1.ping(); //kick thread 1 thread1.join(); //wait until thread1 terminates
thread1.join(1000); //wait until thread2 blocks somewhere in getBundle
ResourceBundle bundle = (ResourceBundle)thread1.bundle; ResourceBundle bundle = (ResourceBundle)thread1.bundle;
String s1 = bundle.getString("Bug4168625Resource3_en_US"); String s1 = bundle.getString("Bug4168625Resource3_en_US");

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2011 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.
*
* 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.
*/
/*
* Portions Copyright (c) 2011 IBM Corporation
*/
/*
* @test
* @bug 6312706
* @summary Sets from Map.entrySet() return distinct objects for each Entry
* @author Neil Richards <neil.richards@ngmr.net>, <neil_richards@uk.ibm.com>
*/
import java.util.concurrent.ConcurrentHashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class DistinctEntrySetElements {
public static void main(String[] args) throws Exception {
final ConcurrentHashMap<String, String> concurrentHashMap =
new ConcurrentHashMap<>();
concurrentHashMap.put("One", "Un");
concurrentHashMap.put("Two", "Deux");
concurrentHashMap.put("Three", "Trois");
Set<Map.Entry<String, String>> entrySet = concurrentHashMap.entrySet();
HashSet<Map.Entry<String, String>> hashSet = new HashSet<>(entrySet);
if (false == hashSet.equals(entrySet)) {
throw new RuntimeException("Test FAILED: Sets are not equal.");
}
if (hashSet.hashCode() != entrySet.hashCode()) {
throw new RuntimeException("Test FAILED: Set's hashcodes are not equal.");
}
}
}