By mainstringargs


2009-03-02 14:59:53 8 Comments

I am using a Collection (a HashMap used indirectly by the JPA, it so happens), but apparently randomly the code throws a ConcurrentModificationException. What is causing it and how do I fix this problem? By using some synchronization, perhaps?

Here is the full stack-trace:

Exception in thread "pool-1-thread-1" java.util.ConcurrentModificationException
        at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
        at java.util.HashMap$ValueIterator.next(Unknown Source)
        at org.hibernate.collection.AbstractPersistentCollection$IteratorProxy.next(AbstractPersistentCollection.java:555)
        at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
        at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
        at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
        at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
        at org.hibernate.engine.Cascade.cascade(Cascade.java:130)

6 comments

@Raedwald 2019-03-13 11:57:02

Modification of a Collection while iterating through that Collection using an Iterator is not permitted by most of the Collection classes. The Java library calls an attempt to modify a Collection while iterating through it a "concurrent modification", which unfortunately suggests the only possible cause is simultaneous modification by multiple threads, but that is not so. Using only one thread it is possible to create an iterator for the Collection (using Collection.iterator(), or an enhanced for loop), start iterating (using Iterator.next(), or equivalently entering the body of the enhanced for loop), modify the Collection, then continue iterating.

To help programmers, some implementations of those Collection classes attempt to detect erroneous concurrent modification, and throw a ConcurrentModificationException if they detect it. However, it is in general not possible and practical to guarantee detection of all concurrent modifications. So erroneous use of the Collection does not always result in a thrown ConcurrentModificationException.

The documentation of ConcurrentModificationException says:

This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible...

Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception...

Note that fail-fast behavior cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast operations throw ConcurrentModificationException on a best-effort basis.

Note that

The documentation of the HashSet, HashMap, TreeSet and ArrayList classes says this:

The iterators returned [directly or indirectly from this class] are fail-fast: if the [collection] is modified at any time after the iterator is created, in any way except through the iterator's own remove method, the Iterator throws a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

Note again that the behaviour "cannot be guaranteed" and is only "on a best-effort basis".

The documentation of several methods of the Map interface say this:

Non-concurrent implementations should override this method and, on a best-effort basis, throw a ConcurrentModificationException if it is detected that the mapping function modifies this map during computation. Concurrent implementations should override this method and, on a best-effort basis, throw an IllegalStateException if it is detected that the mapping function modifies this map during computation and as a result computation would never complete.

Note again that only a "best-effort basis" is required for detection, and a ConcurrentModificationException is explicitly suggested only for the non concurrent (non thread-safe) classes.

Debugging ConcurrentModificationException

So, when you see a stack-trace due to a ConcurrentModificationException, you can not immediately assume that the cause is unsafe multi-threaded access to a Collection. You must examine the stack-trace to determine which class of Collection threw the exception (a method of the class will have directly or indirectly thrown it), and for which Collection object. Then you must examine from where that object can be modified.

  • The most common cause is modification of the Collection within an enhanced for loop over the Collection. Just because you do not see an Iterator object in your source code does not mean there is no Iterator there! Fortunately, one of the statements of the faulty for loop will usually be in the stack-trace, so tracking down the error is usually easy.
  • A trickier case is when your code passes around references to the Collection object. Note that unmodifiable views of collections (such as produced by Collections.unmodifiableList()) retain a reference to the modifiable collection, so iteration over an "unmodifiable" collection can throw the exception (the modification has been done elsewhere). Other views of your Collection, such as sub lists, Map entry sets and Map key sets also retain references to the original (modifiable) Collection. This can be a problem even for a thread-safe Collection, such as CopyOnWriteList; do not assume that thread-safe (concurrent) collectins can never throw the exception.
  • Which operations can modify a Collection can be unexpected in some cases. For example, LinkedHashMap.get() modifies its collection.
  • The hardest cases are when the exception is due to concurrent modification by multiple threads.

Programming to prevent concurrent modification errors

When possible, confine all references to a Collection object, so its is easier to prevent concurrent modifications. Make the Collection a private object or a local variable, and do not return references to the Collection or its iterators from methods. It is then much easier to examine all the places where the Collection can be modified. If the Collection is to be used by multiple threads, it is then practical to ensure that the threads access the Collection only with appropriate synchonization and locking.

@ZhaoGang 2018-07-06 08:02:19

Note that the selected answer cannot be applied to your context directly before some modification, if you are trying to remove some entries from the map while iterating the map just like me.

I just give my working example here for newbies to save their time:

HashMap<Character,Integer> map=new HashMap();
//adding some entries to the map
...
int threshold;
//initialize the threshold
...
Iterator it=map.entrySet().iterator();
while(it.hasNext()){
    Map.Entry<Character,Integer> item=(Map.Entry<Character,Integer>)it.next();
    //it.remove() will delete the item from the map
    if((Integer)item.getValue()<threshold){
        it.remove();
    }

@Robin 2009-03-02 15:04:45

This is not a synchronization problem. This will occur if the underlying collection that is being iterated over is modified by anything other than the Iterator itself.

Iterator it = map.entrySet().iterator();
while (it.hasNext())
{
   Entry item = it.next();
   map.remove(item.getKey());
}

This will throw a ConcurrentModificationException when the it.hasNext() is called the second time.

The correct approach would be

   Iterator it = map.entrySet().iterator();
   while (it.hasNext())
   {
      Entry item = it.next();
      it.remove();
   }

Assuming this iterator supports the remove() operation.

@Tom Hawtin - tackline 2009-03-02 15:29:05

Possibly, but it looks as if Hibernate is doing the iterating, which should be implemented reasonably correctly. There could be callback modifying the map, but that is unlikely. The unpredictability points to an actual concurrency problem.

@Robin 2009-03-02 15:39:22

This exception has nothing to do with threading concurrency, it is caused by the backing store of the iterator being modified. Whether by another thread of not doesn't matter to the iterator. IMHO it is a poorly named exception since it gives an incorrect impression of the cause.

@Robin 2009-03-02 15:42:19

I agree however that if it is unpredictable, there is most likely a threading issue which is causing the conditions for this exception to occur. Which makes it all the more confusing because of the exception name.

@G__ 2011-05-09 20:51:57

This is correct and a better explanation than the accepted answer, but the accepted answer is a nice fix. ConcurrentHashMap is not subject to CME, even inside an iterator (although the iterator is still designed for single-thread access).

@peter 2012-08-21 08:20:11

This solution has no point, because Maps don't have iterator() method. Robin's example would be applicable to e.g. Lists.

@Robin 2012-10-25 13:06:39

I think the point was still served, but you are correct in that my example was wrong. It has been fixed.

@Muneeb Mirza 2016-08-24 12:19:23

I was working on android and it took me like 4 hours to actually find something that pointed out my issue. Thanks alot.

@Chochos 2009-03-02 16:40:37

Try using a ConcurrentHashMap instead of a plain HashMap

@tobiasbayer 2010-08-31 07:37:34

Did that really solve the problem? I am experiencing the same issue but I can most certainly rule out any threading issues.

@Chochos 2010-08-31 14:44:39

Another solution is to create a copy of the map and iterate through that copy instead. Or copy the set of keys and iterate through them, getting the value for each key from the original map.

@tobiasbayer 2010-09-01 06:30:53

It is Hibernate who is iterating through the collection so you cannot simply copy it.

@Valchris 2011-03-16 10:39:26

Instant savior. Going to look into why this worked so well so I don't get more surprises further down the road.

@dantuch 2012-06-10 12:39:34

@CodeBrickie, yes, it somehow does solve the problem that @Robin wrote about. Anyway map = Collections.synchronizedMap(map); doesn't solve anything :) So this is not a threading issue, it appears that ConcurrentHashMap is more noob-safe :)

@Chochos 2012-06-14 04:10:55

ConcurrentHashMap can be modified while it is being iterated and it won't throw. The downside is slower performance.

@Rais Alam 2012-12-24 08:38:21

I guess its not synchronization issue it is problem if modification of same modification while looping same object.

@juanmf 2016-12-14 21:37:56

From ConcurrentHashMap Javadoc Similarly, Iterators, Spliterators and Enumerations return elements reflecting the state of the hash table at some point at or since the creation of the iterator/enumeration. They do not throw ConcurrentModificationException. However, iterators are designed to be used by only one thread at a time.

@Chauyan 2019-06-21 18:23:37

the best answer for this exception. thanks a lot.

@Kashkashio 2019-07-11 11:40:15

should be marked as approved. genius thank you

@Javamann 2009-03-02 16:04:01

Try either CopyOnWriteArrayList or CopyOnWriteArraySet depending on what you are trying to do.

@duffymo 2009-03-02 15:04:28

It sounds less like a Java synchronization issue and more like a database locking problem.

I don't know if adding a version to all your persistent classes will sort it out, but that's one way that Hibernate can provide exclusive access to rows in a table.

Could be that isolation level needs to be higher. If you allow "dirty reads", maybe you need to bump up to serializable.

@TBH 2010-02-02 20:07:13

HashMap is thread-safe. Its not sunchronization issue.

@Narayana Nagireddi 2014-10-08 20:59:50

@TBH How is HashMap thread-safe?

@duffymo 2014-10-08 22:51:38

I think they meant Hashtable. It shipped as part of JDK 1.0. Like Vector, it was written to be thread safe - and slow. Both have been superseded by non-thread safe alternatives: HashMap and ArrayList. Pay for what you use.

Related Questions

Sponsored Content

23 Answered Questions

25 Answered Questions

10 Answered Questions

[SOLVED] Why is subtracting these two times (in 1927) giving a strange result?

  • 2011-07-27 08:15:58
  • Freewind
  • 628578 View
  • 6597 Score
  • 10 Answer
  • Tags:   java date timezone

41 Answered Questions

[SOLVED] How do I efficiently iterate over each entry in a Java Map?

33 Answered Questions

[SOLVED] How do you assert that a certain exception is thrown in JUnit 4 tests?

24 Answered Questions

[SOLVED] What is a serialVersionUID and why should I use it?

3 Answered Questions

[SOLVED] Why is printing "B" dramatically slower than printing "#"?

25 Answered Questions

[SOLVED] How can I safely create a nested directory?

11 Answered Questions

16 Answered Questions

[SOLVED] Why is char[] preferred over String for passwords?

Sponsored Content