From d97dd4d554af79e117af0e26d823fbd200130f41 Mon Sep 17 00:00:00 2001 From: Adam Farley8 Date: Thu, 2 May 2019 06:33:28 -0700 Subject: [PATCH] 8222930: ConcurrentSkipListMap.clone() shares size variable between original and clone Co-authored-by: Martin Buchholz Reviewed-by: martin, smarks --- .../concurrent/ConcurrentSkipListMap.java | 1 + .../jdk/java/util/concurrent/tck/MapTest.java | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java index db14d4baf3a..1cd73476699 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java @@ -1129,6 +1129,7 @@ public class ConcurrentSkipListMap extends AbstractMap clone.entrySet = null; clone.values = null; clone.descendingMap = null; + clone.adder = null; clone.buildFromSorted(this); return clone; } catch (CloneNotSupportedException e) { diff --git a/test/jdk/java/util/concurrent/tck/MapTest.java b/test/jdk/java/util/concurrent/tck/MapTest.java index 4446e084d35..b6d81261f48 100644 --- a/test/jdk/java/util/concurrent/tck/MapTest.java +++ b/test/jdk/java/util/concurrent/tck/MapTest.java @@ -200,6 +200,32 @@ public class MapTest extends JSR166TestCase { 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()); // }