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>
--- 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());
// }