0

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();

Nick Haughton
  • 99
  • 1
  • 11
  • Can you post the stacktrace ? – AllTooSir May 18 '13 at 02:02
  • and you shouldn't be catching a ConcurrentModificationException. – Hovercraft Full Of Eels May 18 '13 at 02:02
  • 1
    Something, some where is making a change to the active towers, this may include changing, adding or removing and element. Try creating an array of elements from the `activeTowers` object (you might like to link to the previous question and include details about what type of object `activeTowers` actually is... – MadProgrammer May 18 '13 at 02:03
  • @MadProgrammer: that should be an answer. Let me up-vote you twice tonight! – Hovercraft Full Of Eels May 18 '13 at 02:04
  • @Noob UnChained The stacktrace is thousands of lines long this is a segment `Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException at java.util.AbstractList$Itr.next(AbstractList.java:343) at towerdefence.Board.paintComponent(Board.java:283) at javax.swing.JComponent.paint(JComponent.java:1037) at javax.swing.JComponent._paintImmediately(JComponent.java:5106) at javax.swing.JComponent.paintImmediately(JComponent.java:4890) at javax.swing.RepaintManager$3.run(RepaintManager.java:814) at javax.swing.RepaintManager$3.run(RepaintManager.java:802) ...` – Nick Haughton May 18 '13 at 02:05
  • `g.drawImage`'s last argument is an `ImageObserver`. You are sending `this` there. The `imageUpdate()` is probably changing `activeTowers` or any other paint component listener. – acdcjunior May 18 '13 at 02:07

2 Answers2

4

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....

rolfl
  • 17,539
  • 7
  • 42
  • 76
  • The interesting part is that this is the only code that deals with the arraylist at all besides when I add the elements. which is this code: `Board.activeTowers.add(new ArcherTower(Input.getYArrayPos(), Input.getXArrayPos(), ArcherTower.tower1ID));` – Nick Haughton May 18 '13 at 02:12
  • @NickHaughton The following code throws CME: `ArrayList x = ...; Iterator it = x.iterator(); x.add(obj); it.next();` – rolfl May 18 '13 at 02:18
0

Carrying on from what our esteemed members have suggested:

1) This error is generally seen when the List is being modified after an Iterator has been extracted.

2) I am looking at your code and it seems alright except this being used in the drawImage() method. This may potentially be altering your List because This has direct access to class members / class variables.

3) This can also happen if multiple threads are accessing the List concurrently. And one of the threads may be trying to alter your List from some other method which share the same instance of the List. I am saying some other method because concurrent read access should not create trouble if multiple threads were accessing this method.

Note: Please all posible code and Stake trace to debug exact problem.

Ravi Trivedi
  • 2,340
  • 2
  • 14
  • 20