Fix the ConcurrentModificationException

Have you inadvertently run into Java’s ConcurrentModificationException? Don’t fret. There are a few different ways to fix the ConcurrentModificationException problem.

Java’s ConcurrentModificationException is thrown when a collection is modified while a Java Iterator is trying to loop through it.

In the following Java code, the commented line will trigger the exception if it is allowed to execute:

package com.mcnz.collections;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

public class FailFastAndSafe {

  public static void main(String[] args) {
    failSafeIterator();
    failFastIterator();
  }
	
  private static void failSafeIterator() {
    String[] data = {"Tomcat", "Undertow", "Kubernetes", "JBoss"};
    List servers = new CopyOnWriteArrayList(data);
    Iterator iterator = servers.iterator();
		
    while (iterator.hasNext()) {
      String server = iterator.next();
      System.out.println(server);
      servers.add("Jetty");
    }	
  }

  private static void failFastIterator() {
    List servers = new ArrayList();
    servers.add("Tomcat");
		
    Iterator iterator = servers.iterator();
    while (iterator.hasNext()) {
      String server = iterator.next();
      System.out.println(server);
      // servers.add("Jetty");
    }
  }
}

ConcurrentModificationException causes

In the failSafeIterator() method, an Iterator has been created based upon the Java collection class named servers. But while the loops processes the list, the underlying collection class will be modified if the commented line of code is allowed to run. The modification of a Java collection while an iterator loops through it triggers the ConcurrentModificationException.

    List servers = new ArrayList();
    servers.add("Tomcat");
		
    Iterator iterator = servers.iterator();
    while (iterator.hasNext()) {
      String server = iterator.next();
      System.out.println(server);
      servers.add("Jetty");  // throws ConcurrentModificationException
    }

You shouldn’t modify a collection while an Iterator loops over it. If you do, the result of the Iterator’s processing may not be in sync with the modified collection, which will make the application’s logic unreliable.

How to fix

How do you fix Java’s ConcurrentModificationException? There are two basic approaches:

  1. Do not make any changes to a collection while an Iterator loops through it
  2. If you can’t stop the underlying collection from being modified during iteration, create a clone of the target data structure and iterate through the clone
  3. Use a fail-safe collection class that will not throw the ConcurrentModificationException
  4. Simply catch the ConcurrentModificationException, log the error, and move on

The obvious way to fix Java’s ConcurrentModificationException is to not concurrently modify a collection. Of course, this is easier said than done.

In our contrived ConcurrentModificationException example above, it is easy to identify where the code modifies the collection. In multi-threaded production environments, it’s possible that the collection is manipulated by a different process that runs a different piece of code. Furthermore, the other process might not always execute as the Iterator goes over the collection, so developers may not be able to reproduce the error consistently. Sometimes it can be difficult determining the cause of the ConcurrentModificationException, but an elimination of the problem is the best approach to take if consistency between the Iterator and the Collection is required.

Fail-safe iterators

If modification of the underlying collection is inevitable, an alternate way to fix the ConcurrentModificationException is to use a fail-safe iterator. These iterators avoid the ConcurrentModificationException by creating a copy of the underlying collection, and iterate through the clone. Since the clone and the original collection are not synchronized with each other, the results generated by looping over a fail-safe iterator may be out of sync with the original collection, but that is the price you have to pay to edit the underlying collection and avoid the ConcurrentModificationException at the same time.

    String[] data = {"Tomcat", "Undertow", "Kubernetes", "JBoss"};
    List servers = new CopyOnWriteArrayList(data);
    Iterator iterator = servers.iterator();
		
    while (iterator.hasNext()) {
      String server = iterator.next();
      System.out.println(server);
      servers.add("Jetty");  // suppresses ConcurrentModificationException 
    }

In the code above, the addition of the name Jetty to the collection of server names does not throw an exception, as the fail-safe CopyOnWriteArrayList is being used.

Debugging applications is always a tedious task, but when it comes to fixing the ConcurrentModificationException, there are many options a developer can take, be it avoiding concurrent updates to the underlying collection class, using a fail-safe iterator, or just handling the exception when the  ConcurrentModificationException happens and moving on.