From 4c999ed180fa9937db895c2aa432db496f2ee63e Mon Sep 17 00:00:00 2001
From: Doug Lea
Date: Wed, 24 Aug 2016 12:50:37 -0700
Subject: [PATCH] 8163353: NPE in ConcurrentHashMap.removeAll()
Reviewed-by: martin, psandoz, redestad, alanb
---
.../java/util/concurrent/ConcurrentHashMap.java | 5 ++++-
.../concurrent/tck/ConcurrentHashMapTest.java | 15 +++++++++++++++
2 files changed, 19 insertions(+), 1 deletion(-)
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
*/