Bug in ArrayList iterator

Paul Sandoz paul.sandoz at oracle.com
Wed Jan 7 11:33:30 UTC 2015


On Jan 7, 2015, at 11:56 AM, Chris Hegarty <chris.hegarty at oracle.com> wrote:

> On 07/01/15 10:47, Daniel Fuchs wrote:
>> On 07/01/15 11:31, Paul Sandoz wrote:
>>> 
>>> On Jan 7, 2015, at 10:45 AM, Remi Forax <forax at univ-mlv.fr> wrote:
>>> 
>>>> A simple Java question, what this code does ?
>>>> 
>>>>  ArrayList<String> list = new ArrayList<>();
>>>>  list.add("foo");
>>>>  list.add("bar");
>>>>  for(String s: list) {
>>>>    list.remove(s);
>>>>  }
>>>> 
>>>> :(
>>>> 
>>> 
>>> We could improve the best-effort basis by which
>>> ConcurrentModificationException is thrown by snapshotting the
>>> collection size on construction of the iterator
> 
> This was my thought too.
> 
>  diff --git a/src/java.base/share/classes/java/util/ArrayList.java b/src/java.base/share/classes/java/util/ArrayList.java
> --- a/src/java.base/share/classes/java/util/ArrayList.java
> +++ b/src/java.base/share/classes/java/util/ArrayList.java
> @@ -853,9 +853,10 @@
>         int cursor;       // index of next element to return
>         int lastRet = -1; // index of last element returned; -1 if no such
>         int expectedModCount = modCount;
> +        int itrSize = size;
> 
>         public boolean hasNext() {
> -            return cursor != size;
> +            return cursor != itrSize;
>         }
> 
>         @SuppressWarnings("unchecked")
> @@ -881,6 +882,7 @@
>                 cursor = lastRet;
>                 lastRet = -1;
>                 expectedModCount = modCount;
> +                itrSize--;
>             } catch (IndexOutOfBoundsException ex) {
>                 throw new ConcurrentModificationException();
>             }
> @@ -909,7 +911,7 @@
>         }
> 
>         final void checkForComodification() {
> -            if (modCount != expectedModCount)
> +            if (modCount != expectedModCount || size != itrSize)
>                 throw new ConcurrentModificationException();
>         }
>     }
> 

Under what conditions can the mod count be the same but the size is different? Would this not indicate there was a bug in some other method that made a structural change but did not update the mod count? Same apples to this:

  Object[] elementData = ArrayList.this.elementData;
  if (i >= elementData.length)
      throw new ConcurrentModificationException();

(Note as per usual in these discussions i am not referring to concurrent operation from multiple threads, under such conditions all bets are off.)

Unfortunately the change history in openjdk only goes back so far, and i agree with Doug that there might be some reason why this change was not made earlier on (it seems like an "obvious" thing to do).

Paul.





More information about the core-libs-dev mailing list