8222930: ConcurrentSkipListMap.clone() shares size variable between original and clone
authordl
Thu, 02 May 2019 06:33:28 -0700
changeset 54682 79d13fd7db9c
parent 54681 edd709e64ea1
child 54683 3ffdc15cd044
8222930: ConcurrentSkipListMap.clone() shares size variable between original and clone Reviewed-by: martin, smarks Contributed-by: Adam Farley8 <adam.farley@uk.ibm.com>, Martin Buchholz <martinrb@google.com>
src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
test/jdk/java/util/concurrent/tck/MapTest.java
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Thu May 02 11:55:16 2019 +0100
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Thu May 02 06:33:28 2019 -0700
@@ -1129,6 +1129,7 @@
             clone.entrySet = null;
             clone.values = null;
             clone.descendingMap = null;
+            clone.adder = null;
             clone.buildFromSorted(this);
             return clone;
         } catch (CloneNotSupportedException e) {
--- a/test/jdk/java/util/concurrent/tck/MapTest.java	Thu May 02 11:55:16 2019 +0100
+++ b/test/jdk/java/util/concurrent/tck/MapTest.java	Thu May 02 06:33:28 2019 -0700
@@ -200,6 +200,32 @@
         assertEquals(size1 + size2, m1.size());
     }
 
+    /**
+     * 8222930: ConcurrentSkipListMap.clone() shares size variable between original and clone
+     */
+    public void testClone() {
+        final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+        final int size = rnd.nextInt(4);
+        final Map map = impl.emptyMap();
+        for (int i = 0; i < size; i++)
+            map.put(impl.makeKey(i), impl.makeValue(i));
+        final Map clone = cloneableClone(map);
+        if (clone == null) return;      // not cloneable?
+
+        assertEquals(size, map.size());
+        assertEquals(size, clone.size());
+        assertEquals(map.isEmpty(), clone.isEmpty());
+
+        clone.put(impl.makeKey(-1), impl.makeValue(-1));
+        assertEquals(size, map.size());
+        assertEquals(size + 1, clone.size());
+
+        clone.clear();
+        assertEquals(size, map.size());
+        assertEquals(0, clone.size());
+        assertTrue(clone.isEmpty());
+    }
+
 //     public void testFailsIntentionallyForDebugging() {
 //         fail(impl.klazz().getSimpleName());
 //     }