-
Bug
-
Resolution: Not an Issue
-
P3
-
None
-
8u45, 8-pool
-
x86
-
linux
FULL PRODUCT VERSION :
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux twilson3-linux 3.13.0-49-generic #83-Ubuntu SMP Fri Apr 10 20:11:33 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
In java 8 the implementation of chaining to handle hash collisions was changed. For bins of at most 8 colliding elements, the elements are stored in a linked list. New collisions are appended to this list.
This has the effect of making it possible to for an iterator over a concurrent hash map to infinite loop if new colliding entries are continually added to the bin being iterated over.
In contrast, java 7 will prepend colliding elements. This guarantees that an iterator will always be able to complete no matter how the map is concurrently modified.
REGRESSION. Last worked in version 7u80
ADDITIONAL REGRESSION INFORMATION:
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached test case on java 8. It will never complete.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Test completes.
ACTUAL -
Test loops indefinitely.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Test {
public static void main(String[] args) {
Map<Long, Long> map = new ConcurrentHashMap<>();
map.put(0L, 0L);
map.put((1L << 32) + 1, 0L); // hash collision
for (long key : map.keySet()) {
map.put(key, map.remove(key));
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Avoid the exact conditions exercised by the test (modifying the entry being iterated over). This can be done by making a defensive copy or detecting when an element has already been iterated over by the current iterator.
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux twilson3-linux 3.13.0-49-generic #83-Ubuntu SMP Fri Apr 10 20:11:33 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
In java 8 the implementation of chaining to handle hash collisions was changed. For bins of at most 8 colliding elements, the elements are stored in a linked list. New collisions are appended to this list.
This has the effect of making it possible to for an iterator over a concurrent hash map to infinite loop if new colliding entries are continually added to the bin being iterated over.
In contrast, java 7 will prepend colliding elements. This guarantees that an iterator will always be able to complete no matter how the map is concurrently modified.
REGRESSION. Last worked in version 7u80
ADDITIONAL REGRESSION INFORMATION:
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached test case on java 8. It will never complete.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Test completes.
ACTUAL -
Test loops indefinitely.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Test {
public static void main(String[] args) {
Map<Long, Long> map = new ConcurrentHashMap<>();
map.put(0L, 0L);
map.put((1L << 32) + 1, 0L); // hash collision
for (long key : map.keySet()) {
map.put(key, map.remove(key));
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Avoid the exact conditions exercised by the test (modifying the entry being iterated over). This can be done by making a defensive copy or detecting when an element has already been iterated over by the current iterator.