-
Bug
-
Resolution: Fixed
-
P2
-
8, 9
-
b26
-
generic
-
generic
-
Verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8196531 | 9u-open | Doug Lea | P2 | Resolved | Fixed | master |
JDK-8208977 | 8u201 | Ramanand Patil | P2 | Resolved | Fixed | b01 |
JDK-8205674 | 8u192 | Deepak Kejriwal | P2 | Resolved | Fixed | b01 |
JDK-8216879 | emb-8u201 | Ramanand Patil | P2 | Resolved | Fixed | master |
FULL PRODUCT VERSION :
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
A DESCRIPTION OF THE PROBLEM :
Javadoc allows to use Iterator.remove() and Entry.setValue() when iterating over HashMap:
"If the map is modified while an iteration over the set is in progress (except through the iterator's own remove operation, or through the setValue operation on a map entry returned by the iterator) the results of the iteration are undefined."
However it's possible that setValue() doesn't work if remove() was called for some of previous entries. It may happen when remove() leads to untreeify() call - some TreeNodes are replaced by Nodes, but iterator continues to iterate over old instances hence setValue changes the value in the replaced node. (Test case attached)
REGRESSION. Last worked in version 7u80
REPRODUCIBILITY :
This bug can be reproduced always.
JDK-8186171
---------- BEGIN SOURCE ----------
import java.util.*;
public class Main {
static class Key {
@Override
public int hashCode() {
return 0; // to put keys in one bucket
}
}
public static void main(String[] args) {
List<Key> keys = new ArrayList<>();
for (int i = 0; i < 11; ++i) { // 11 is big enough for a map to use tree nodes
keys.add(new Key());
}
Map<Object, Object> data = Collections.singletonMap(keys.get(10), 1);
Map<Object, Object> result = new HashMap<>();
for (Object key : keys) {
result.put(key, null);
}
for (Iterator<Map.Entry<Object, Object>> iter = result.entrySet().iterator(); iter.hasNext();) {
Map.Entry<Object, Object> entry = iter.next();
Object value = data.get(entry.getKey());
if (value == null) {
iter.remove();
} else {
entry.setValue(value); // this call doesn't set the value
}
}
if (result.containsValue(null)) {
System.out.println("FAILED");
} else {
System.out.println("OK");
}
}
}
---------- END SOURCE ----------
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
A DESCRIPTION OF THE PROBLEM :
Javadoc allows to use Iterator.remove() and Entry.setValue() when iterating over HashMap:
"If the map is modified while an iteration over the set is in progress (except through the iterator's own remove operation, or through the setValue operation on a map entry returned by the iterator) the results of the iteration are undefined."
However it's possible that setValue() doesn't work if remove() was called for some of previous entries. It may happen when remove() leads to untreeify() call - some TreeNodes are replaced by Nodes, but iterator continues to iterate over old instances hence setValue changes the value in the replaced node. (Test case attached)
REGRESSION. Last worked in version 7u80
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.*;
public class Main {
static class Key {
@Override
public int hashCode() {
return 0; // to put keys in one bucket
}
}
public static void main(String[] args) {
List<Key> keys = new ArrayList<>();
for (int i = 0; i < 11; ++i) { // 11 is big enough for a map to use tree nodes
keys.add(new Key());
}
Map<Object, Object> data = Collections.singletonMap(keys.get(10), 1);
Map<Object, Object> result = new HashMap<>();
for (Object key : keys) {
result.put(key, null);
}
for (Iterator<Map.Entry<Object, Object>> iter = result.entrySet().iterator(); iter.hasNext();) {
Map.Entry<Object, Object> entry = iter.next();
Object value = data.get(entry.getKey());
if (value == null) {
iter.remove();
} else {
entry.setValue(value); // this call doesn't set the value
}
}
if (result.containsValue(null)) {
System.out.println("FAILED");
} else {
System.out.println("OK");
}
}
}
---------- END SOURCE ----------
- backported by
-
JDK-8196531 HashMap: Entry.setValue may not work after Iterator.remove() called for previous entries
- Resolved
-
JDK-8205674 HashMap: Entry.setValue may not work after Iterator.remove() called for previous entries
- Resolved
-
JDK-8208977 HashMap: Entry.setValue may not work after Iterator.remove() called for previous entries
- Resolved
-
JDK-8216879 HashMap: Entry.setValue may not work after Iterator.remove() called for previous entries
- Resolved
- relates to
-
JDK-8205399 Set node color on pinned HashMap.TreeNode deletion
- Closed