0

this is probably the closest case to mine, but that didn't help either.

I'm getting the ConcurrentModificationException here:

for (Iterator<ProjectileBase> iterator = projectiles.iterator(); iterator.hasNext();) {
        ProjectileBase proj = iterator.next();  < here
        if (proj == null || !proj.isValid()) {
            iterator.remove();
            continue;
        }
        if (((!proj.ignoreRange()) ? proj.lived <= proj.data.getRange() : true)){
            proj.lived++;
            proj.onTick();
        } else {
            MissileHitEvent event = new MissileHitEvent(proj.shooter, proj.wand, proj, false, null);
            Bukkit.getPluginManager().callEvent(event);
            if (!event.isCancelled()) {
                iterator.remove();
                continue;
            } else {
                proj.lived = 0;
            }
        }
    }

Even though I did as suggested here ?

The list is specified like this:

private List<ProjectileBase> projectiles = new ArrayList<ProjectileBase>();

which is intialized on the class construction. What's the problem?

EDIT: console log:

[10:01:58] [Craft Scheduler Thread - 3754/WARN]: Exception in thread "Craft Scheduler Thread - 3754" 
[10:01:58] [Craft Scheduler Thread - 3754/WARN]: org.apache.commons.lang.UnhandledException: Plugin MagicWands v1.0 generated an exception while executing task 247
    at org.bukkit.craftbukkit.v1_9_R2.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:57)
    at com.destroystokyo.paper.ServerSchedulerReportingWrapper.run(ServerSchedulerReportingWrapper.java:22)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)
    at io.jettymc.DataHolders.ProjectileManager.iterate(ProjectileManager.java:117)
    at io.jettymc.DataHolders.ProjectileManager$1.run(ProjectileManager.java:232)
    at org.bukkit.craftbukkit.v1_9_R2.scheduler.CraftTask.run(CraftTask.java:58)
    at org.bukkit.craftbukkit.v1_9_R2.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:53)
    ... 4 more

EDIT 2: Well, I guess it's worth telling, I'm building this project on Bukkit/Spigot (Minecraft server & API).. but I doubt it's the cause of this error?

Community
  • 1
  • 1
jetp250
  • 63
  • 5

2 Answers2

1

To help narrow down the problem, there is a trick that might help.

Assuming projectiles is the only reference to the ArrayList, you can temporarily replace it with an immutable list, while you're iterating, so only the Iterator can modify the list. If some other code tries to modify the list, an exception will occur, which should let you know where it happens, assuming your error handling is not messed up.

Example:

List<ProjectileBase> projectilesHold = projectiles;
projectiles = Collections.unmodifiableList(projectiles);
try {
    for (Iterator<ProjectileBase> iterator = projectilesHold.iterator(); iterator.hasNext();) {
        // other code here is unchanged
    }
} finally {
    projectiles = projectilesHold;
}

The code saves the modifiable list in the "hold" variable, then wraps the list to make it unmodifiable. The finally block will ensure that the modifiable list is restored, no matter what.

The for loop iterator was then modified to use the modifiable list in "hold", so its remove() method works, but anywhere else the projectiles field is now unmodifiable for the duration of the iteration.

This is for debug only. Once you identify the problem and correct it, remove the logic again.

Andreas
  • 154,647
  • 11
  • 152
  • 247
0

Check the documentation of ConcurrentModificationException and ArrayList

https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html

https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html

To resolve your issue please check the following code.

For Example,

import java.util.*;

public class HelloWorld{

     public static void main(String []args){
        List<String> animals = new ArrayList<>();
        animals.add("Cat1");
        animals.add("Cat2");
        animals.add("Cat3");
        animals.add("Cat4");
        animals.add("Cat5");

        for(ListIterator<String> iterator = animals.listIterator(); iterator.hasNext();) {
            String name = iterator.next();
            if (name.equals("Cat2")) {
                iterator.remove();
                continue;
            }
            System.out.println(name);
        }
     }
}

Cheers!!!

Amit Goyal
  • 56
  • 2
  • Pretty much the only difference I see is that you changed Iterator to ListIterator? – jetp250 Oct 15 '16 at 07:39
  • Didn't mean to send that comment yet, sorry.. Anyway, I tried that, and it works of course, but it also worked with the normal Iterator, meaning the error isn't there. – jetp250 Oct 15 '16 at 07:39