Search code examples
javapaintrepaintconcurrentmodification

Concurrent Modification Exception Cause by Painting?


I have been having a lot of trouble with the Concurrent Modification Exception error. With the help of the community I managed to fix my last error, however I think this error is more puzzling.

I am now getting a concurrent modification error while painting, I am worried that this error occurs in the paint function itself. Unlike my last error I am nto removing an entity, in that case I completely understood what was going on just not how to fix it, this error on the other hand I do not understand.

 TowerItr = activeTowers.iterator();

            while (TowerItr.hasNext()) {
                try {

                theTower = (ArcherTower) TowerItr.next();


                g.drawImage(tower, theTower.y * Map.blockSize, theTower.x * Map.blockSize, this);

                } catch (ConcurrentModificationException e) {


                }
            }

The line that throws the exception is this one: theTower = (ArcherTower) TowerItr.next();


Solution

  • There are always two sides to a ConcurrentModificationException (CME), and only one side reports the error.

    In this case, your code looks perfectly fine. You are looping through the members of the activeTowers.

    The stack trace will show you nothing that you don't already know.... you have a CME.

    What you need to find out is where you are adding/removing data from the activeTowers collection.

    In many cases, there are reasonably easy fixes. A probable fix is to synchronize the access to the activeTowers array in every place it is used. This may be quite hard to do.

    Another option is to use a collection from the java.util.concurrent.* package, and to use the toArray(...) methods to get a snapshot of the collection, and then you can iterate that snapshot in your while loop.

    // activeTower must be something from java.util.concurrent.*
    for (ArcherTower theTower : activeTower.toArray(new ArcherTower[0]) {
        g.drawImage(tower, theTower.y * Map.blockSize, theTower.x * Map.blockSize, this);
    }
    

    I should add that if you use a java.util.concurrent.* collection, then the iterator() will return a 'stable' iterator too (will not throw CME, and may (or may not) reflect changes in the collection)

    Bottom line is that a CME only tells you half the story.... and only your code will tell you the rest....