From a351c9acd95495387aaa4bf0a60895f9d119c6d8 Mon Sep 17 00:00:00 2001 From: Luke Wahlmeier Date: Tue, 30 May 2017 15:01:10 -0600 Subject: [PATCH] Fixed issue with toArray on value/keySet in ConcurrentHashMap --- classpath/avian/Data.java | 10 ++++++---- test/ConcurrentHashMapTest.java | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/classpath/avian/Data.java b/classpath/avian/Data.java index 0914362e8..727fe3047 100644 --- a/classpath/avian/Data.java +++ b/classpath/avian/Data.java @@ -15,7 +15,6 @@ import java.util.AbstractSet; import java.util.Collection; import java.util.Iterator; -import java.util.Collections; public class Data { public static int nextPowerOfTwo(int n) { @@ -28,10 +27,10 @@ public static boolean equal(V a, V b) { return a == null ? b == null : a.equals(b); } - public static T[] toArray(Collection collection, T[] array) { + public static T[] toArray(Collection collection, T[] array) { Class c = array.getClass().getComponentType(); - - if (array.length < collection.size()) { + int Csize = collection.size(); + if (array.length < Csize) { array = (T[]) java.lang.reflect.Array.newInstance(c, collection.size()); } @@ -39,6 +38,9 @@ public static T[] toArray(Collection collection, T[] array) { for (Object o: collection) { if (c.isInstance(o)) { array[i++] = (T) o; + if(Csize <= i) { + break; + } } else { throw new ArrayStoreException(); } diff --git a/test/ConcurrentHashMapTest.java b/test/ConcurrentHashMapTest.java index f0d271f41..70f77a9c7 100644 --- a/test/ConcurrentHashMapTest.java +++ b/test/ConcurrentHashMapTest.java @@ -1,5 +1,7 @@ import java.util.Iterator; import java.util.Map; +import java.util.Random; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentHashMap; @@ -13,6 +15,31 @@ private static void expect(boolean v) { if (! v) throw new RuntimeException(); } + private static void toArrayConcurrentMod() { + final AtomicBoolean run = new AtomicBoolean(true); + final Random RND = new Random(); + final ConcurrentHashMap map = new ConcurrentHashMap(); + Thread t = new Thread(new Runnable() { + @Override + public void run() { + while(run.get()) { + map.put(RND.nextInt(), RND.nextInt()); + while(map.size() > 500) { + for(Integer i: map.keySet()) { + map.remove(i); + break; + } + } + } + }}); + t.setDaemon(true); + t.start(); + for(int i=0; i<1000; i++) { + map.values().toArray(); + } + run.set(false); + } + public static void main(String[] args) throws Throwable { final ConcurrentMap map = new ConcurrentHashMap(); final int[] counter = new int[1]; @@ -103,6 +130,8 @@ public void run() { map.notifyAll(); } } + + toArrayConcurrentMod(); } private static void populateCommon(ConcurrentMap map) {