diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java index aadf3ca32a9..1d80077b58c 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -4566,7 +4566,10 @@ public class ConcurrentHashMap extends AbstractMap boolean modified = false; // Use (c instanceof Set) as a hint that lookup in c is as // efficient as this view - if (c instanceof Set && c.size() > map.table.length) { + Node[] t; + if ((t = map.table) == null) { + return false; + } else if (c instanceof Set && c.size() > t.length) { for (Iterator it = iterator(); it.hasNext(); ) { if (c.contains(it.next())) { it.remove(); diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java index c521b7edd58..26095ad1bb0 100644 --- a/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java +++ b/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java @@ -359,6 +359,21 @@ public class ConcurrentHashMapTest extends JSR166TestCase { assertTrue(s.contains(five)); } + /** + * Test keySet().removeAll on empty map + */ + public void testKeySet_empty_removeAll() { + ConcurrentHashMap map = new ConcurrentHashMap<>(); + Set set = map.keySet(); + set.removeAll(Collections.emptyList()); + assertTrue(map.isEmpty()); + assertTrue(set.isEmpty()); + // following is test for JDK-8163353 + set.removeAll(Collections.emptySet()); + assertTrue(map.isEmpty()); + assertTrue(set.isEmpty()); + } + /** * keySet.toArray returns contains all keys */