I have a static HashMap<UUID, MyObject> ALL = new HashMap<>();
which is used in multi-threading.
To reproduce the error, I made this code:
HashMap<Integer, String> list = new HashMap<>();
list.put(1, "str 1");
list.put(2, "str 2");
new Thread(() -> {
while(true) {
ArrayList<String> val;
synchronized(list) {
val = new ArrayList<>(list.values());
}
System.out.println(val.toString());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(() -> {
while(true) {
list.put(new Random().nextInt(), "some str");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
But, after some seconds (around 10), I get this error with Java 16 and Java 17:
java.lang.ArrayIndexOutOfBoundsException: Index 2 out of bounds for length 2
at java.util.HashMap.valuesToArray(HashMap.java:973) ~[?:?]
at java.util.HashMap$Values.toArray(HashMap.java:1050) ~[?:?]
at java.util.ArrayList.<init>(ArrayList.java:181) ~[?:?]
With Java 8, I get this:
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1473)
at java.util.HashMap$ValueIterator.next(HashMap.java:1502)
at java.util.AbstractCollection.toArray(AbstractCollection.java:141)
at java.util.ArrayList.<init>(ArrayList.java:178)
To test, I remove synchronized
key-word, then try again in Java 17 and I get this:
java.util.ConcurrentModificationException: null
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1631) ~[?:?]
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[?:?]
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[?:?]
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[?:?]
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[?:?]
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:?]
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) ~[?:?]
Those error seems very strange, especially the first one. I suspect that they comes from the JRE itself. I'm using Java 17.0.1 build 17.0.1+12-LTS-39.
How can I get all values from another thread?