Why doesn't this code throw a ConcurrentModificationException?

Paul Boddington

Why doesn't this code throw a ConcurrentModificationException? It modifies a Collection while iterating through it, without using the Iterator.remove() method, which is meant to be the only safe way of removing.

List<String> strings = new ArrayList<>(Arrays.asList("A", "B", "C"));
for (String string : strings)
    if ("B".equals(string))
        strings.remove("B");
System.out.println(strings);

I get the same result if I replace the ArrayList with a LinkedList. However if I change the list to ("A", "B", "C", "D) or just ("A", "B") I get the exception as expected. What is going on? I am using jdk1.8.0_25 if that is relevant.

EDIT

I've found the following link

http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4902078

The relevant section is

The naive solution is to add comodification checks to hasNext in AbstractList, but this doubles the cost of comodification checking. It turns out that it is sufficient to do the test only on the last iteration, which adds virtually nothing to the cost. In other words, the current implementation of hasNext:

    public boolean hasNext() {
        return nextIndex() < size;
    }

Is replaced by this implementation:

    public boolean hasNext() {
        if (cursor != size())
            return true;
        checkForComodification();
        return false;
    }

This change will not be made because a Sun-internal regulatory body rejected it. The formal ruling indicated that the change "has demonstrated the potential to have significant compatibility impact upon existing code." (The "compatibility impact" is that the fix has the potential to replace silent misbehavior with a ConcurrentModificationException.)

Mshnik

As a general rule, ConcurrentModificationExceptions are thrown when the modification is detected, not caused. If you never access the iterator after the modification, it won't throw an exception. This minute detail makes ConcurrentModificationExceptions rather unreliable for detecting misuse of data structures, unfortunately, as they only are thrown after the damage has been done.

This scenario doesn't throw a ConcurrentModificationException because next() doesn't get called on the created iterator after the modification.

For-each loops are really iterators, so your code actually looks like this:

List<String> strings = new ArrayList<>(Arrays.asList("A", "B", "C"));
Iterator<String> iter = strings.iterator();
while(iter.hasNext()){
    String string = iter.next();
    if ("B".equals(string))
        strings.remove("B");
}
System.out.println(strings);

Consider your code running on the list you provided. The iterations look like:

  1. hasNext() returns true, enter loop, -> iter moves to index 0, string = "A", not removed
  2. hasNext() returns true, continue loop -> iter moves to index 1, string = "B", removed. strings now has length 2.
  3. hasNext() returns false (iter is currently at the last index, no more indices to go), exit loop.

Thus, as ConcurrentModificationExceptions are thrown when a call to next() detects a that a modification has been made, this scenario narrowly avoids such an exception.

For your other two results, we do get exceptions. For "A", "B", "C", "D", after removing "B" we are still in the loop, and next() detects the ConcurrentModificationException, whereas for "A", "B" I'd imagine it's some kind of ArrayIndexOutOfBounds that's being caught and re-thrown as a ConcurrentModificationException

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Why doesn't my sample throw ConcurrentModificationException

From Dev

Why doesn't this ruby code throw an exception?

From Dev

Why does the following code using Iterator next() and remove() throw ConcurrentModificationException?

From Dev

Collection throws or doesn't throw ConcurrentModificationException based on the contents of the Collection

From Dev

Why asInstanceOf doesn't throw a ClassCastException?

From Dev

Why doesn't this list throw a ClassCastException?

From Java

Why doesn't this statement throw a StackOverflowError?

From Dev

Why doesn't this statement throw a StackOverflowError?

From Dev

Why doesn't duplicate IDs throw an error?

From Dev

Why doesn't following java code throw java.lang.StringIndexOutOfBoundsException when there is no element present at index 1?

From Dev

Why doesn't following java code throw java.lang.StringIndexOutOfBoundsException when there is no element present at index 1?

From Dev

Why doesn't the compiler spot certain causes of ConcurrentModificationException

From Dev

Why doesn't the compiler spot certain causes of ConcurrentModificationException

From Dev

Why iterator.remove does not throw ConcurrentModificationException

From Dev

why this code doesn't run?

From Dev

Why the code doesn't compile

From Dev

Cuda device code doesn't throw an error when segfaults

From Dev

Jersey Client 2.19 doesn't throw exceptions on bad status code

From Dev

Why doesn't the Clojure Compiler throw an error for an incorrect type hint?

From Java

Why doesn't incrementing Nullable<int> throw an exception?

From Dev

Why illegal constant names doesn't throw errors using define()?

From Dev

Why doesn't jasper report throw a JRFontNotFoundException if font for PDF is missing?

From Dev

Why doesn't window.something throw an error?

From Dev

Why PHP doesn't throw "undefined offset" notice anymore?

From Dev

Why doesn't System.out.println() throw NullPointerException?

From Dev

Why doesn't my Angular ngModel example throw an error?

From Dev

Why doesn't my javascript function throw up an error?

From Dev

Why doesn't the compiler throw an error saying "No return statement"?

From Dev

CommitFailedException doesn't throw

Related Related

  1. 1

    Why doesn't my sample throw ConcurrentModificationException

  2. 2

    Why doesn't this ruby code throw an exception?

  3. 3

    Why does the following code using Iterator next() and remove() throw ConcurrentModificationException?

  4. 4

    Collection throws or doesn't throw ConcurrentModificationException based on the contents of the Collection

  5. 5

    Why asInstanceOf doesn't throw a ClassCastException?

  6. 6

    Why doesn't this list throw a ClassCastException?

  7. 7

    Why doesn't this statement throw a StackOverflowError?

  8. 8

    Why doesn't this statement throw a StackOverflowError?

  9. 9

    Why doesn't duplicate IDs throw an error?

  10. 10

    Why doesn't following java code throw java.lang.StringIndexOutOfBoundsException when there is no element present at index 1?

  11. 11

    Why doesn't following java code throw java.lang.StringIndexOutOfBoundsException when there is no element present at index 1?

  12. 12

    Why doesn't the compiler spot certain causes of ConcurrentModificationException

  13. 13

    Why doesn't the compiler spot certain causes of ConcurrentModificationException

  14. 14

    Why iterator.remove does not throw ConcurrentModificationException

  15. 15

    why this code doesn't run?

  16. 16

    Why the code doesn't compile

  17. 17

    Cuda device code doesn't throw an error when segfaults

  18. 18

    Jersey Client 2.19 doesn't throw exceptions on bad status code

  19. 19

    Why doesn't the Clojure Compiler throw an error for an incorrect type hint?

  20. 20

    Why doesn't incrementing Nullable<int> throw an exception?

  21. 21

    Why illegal constant names doesn't throw errors using define()?

  22. 22

    Why doesn't jasper report throw a JRFontNotFoundException if font for PDF is missing?

  23. 23

    Why doesn't window.something throw an error?

  24. 24

    Why PHP doesn't throw "undefined offset" notice anymore?

  25. 25

    Why doesn't System.out.println() throw NullPointerException?

  26. 26

    Why doesn't my Angular ngModel example throw an error?

  27. 27

    Why doesn't my javascript function throw up an error?

  28. 28

    Why doesn't the compiler throw an error saying "No return statement"?

  29. 29

    CommitFailedException doesn't throw

HotTag

Archive