ConcurrentModificationException

Discussion in 'Plugin Development' started by gamerx93, Feb 22, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    gamerx93

    I'm having a problem with my plugin when there are other plugins loaded, there is a chance that the following Error is thrown:
    Code:
    19:18:20 [SEVERE] java.util.ConcurrentModificationException
    19:18:20 [SEVERE]      at java.util.HashMap$HashIterator.nextEntry(HashMap.java:806)
    19:18:20 [SEVERE]      at java.util.HashMap$KeyIterator.next(HashMap.java:841)
    19:18:20 [SEVERE]      at net.minecraft.server.World.a(World.java:2358)
    19:18:20 [SEVERE]      at net.minecraft.server.ChunkLoader.a(ChunkLoader.java:163)
    19:18:20 [SEVERE]      at net.minecraft.server.ChunkRegionLoader.a(ChunkRegionLoader.java:75)
    19:18:20 [SEVERE]      at net.minecraft.server.ChunkProviderServer.saveChunk(ChunkProviderServer.java:163)
    19:18:20 [SEVERE]      at net.minecraft.server.ChunkProviderServer.saveChunks(ChunkProviderServer.java:212)
    19:18:20 [SEVERE]      at net.minecraft.server.World.save(World.java:277)
    19:18:20 [SEVERE]      at org.bukkit.craftbukkit.CraftWorld.save(CraftWorld.java:580)
    19:18:20 [SEVERE]      at org.bukkit.command.defaults.SaveCommand.execute(SaveCommand.java:25)
    19:18:20 [SEVERE]      at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:168)
    19:18:20 [SEVERE]      at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:402)
    19:18:20 [SEVERE]      at net.tgxn.bukkit.backup.threading.PrepareBackup.prepareBackup(PrepareBackup.java:108)
    19:18:20 [SEVERE]      at net.tgxn.bukkit.backup.threading.PrepareBackup.checkShouldDoBackup(PrepareBackup.java:84)
    19:18:20 [SEVERE]      at net.tgxn.bukkit.backup.threading.PrepareBackup.run(PrepareBackup.java:35)
    19:18:20 [SEVERE]      at org.bukkit.craftbukkit.scheduler.CraftWorker.run(CraftWorker.java:34)
    19:18:20 [SEVERE]      at java.lang.Thread.run(Thread.java:722)
    
    I have a bug report on GitHub, but I have no idea how to solve it.
    https://github.com/gamerx/Backup/issues/63

    Can someone give me a small amount of insight into this please?
     
  2. Offline

    bassfader

    If i'm not mistaken, this exception can occur when you are iterating through a list and while you are doing so, you are modifying the list (by deleting an entry for example).

    e.g. the following code should raise such an exception (assuming "list" is a List<String> object):
    Code:
    for (String s : list) {
        if (s.equals("test")) list.remove(s)
    }
     
  3. Offline

    Technius

    A ConcurrentModificationException(CME) means that an ArrayList/Map has been accessed by multiple threads at the same time. The way to solve this is to synchronize, which is to only allow one thread at a time. Even if you spam synchronized blocks, it will still have this error. Luckily, Java provides a class which already has everything synchronized. Use ConcurrentHashMap instead of HashMaps where your stuff is being accessed by multiple threads.
     
  4. Offline

    hatstand

    One way to get around such things is to create a list of items to remove while you're iterating through the list, then use removeAll() once the loop is finished.
     
  5. Offline

    Technius

    That would not be needed, as CopyOnWriteArrayList is the ArrayList equivalent of the ConcurrentHashMap.
     
  6. Offline

    gamerx93

    Sorry, I'm not really understaning this very well.

    The piece of code that is causing this ST is this:
    Code:
            ConsoleCommandSender consoleCommandSender = server.getConsoleSender();
            server.dispatchCommand(consoleCommandSender, "save-all");
    I'm not sure how to make this run as a synchronous thread?
     
  7. Offline

    hatstand

    I wasn't aware of that class, handy.
     
  8. Offline

    Technius

    That should work without an exception. If it continues to throw CME's, put it in a synchronized block.
     
  9. Offline

    Zimp

    The stack trace is probably caused by an attempt to save the world from one thread while it is being modified in another (most likely the main server thread). You'll need to use something like:

    Code:
    server.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() {
            ConsoleCommandSender consoleCommandSender = server.getConsoleSender();
            server.dispatchCommand(consoleCommandSender, "save-all");
    }});
    
     
Thread Status:
Not open for further replies.

Share This Page