ConcurrentModificationException?

Discussion in 'Plugin Development' started by flaaghara, Jun 19, 2013.

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

    flaaghara

    So I initialize an object whose instance data includes an ArrayList of Blocks. My main plugin class is the one that initializes the BlockSearchManager object whose addBlocks() method is written here. Whenever addBlocks() is run, I get a ConcurrentModificationException. Any idea how to fix this?

    Code:java
    1. public void addBlocks() {
    2. for(Block block: blockList)
    3. for(int x = -1; x <= 1; x++)
    4. for(int y = -1;y <= 1; y++)
    5. for(int z = -1; z <= 1; z++) {
    6. if(block.getRelative(x, y, z).getType() == block.getType() && !blockList.contains(block.getRelative(x, y, z))) {
    7. blockList.add(block.getRelative(x, y, z));
    8. }
    9. }
    10. }


    Here's the stacktrace.

    Code:
    2013-06-19 21:30:50 [SEVERE] Could not pass event BlockBreakEvent to Plugin v0.1
    org.bukkit.event.EventException
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:427)
        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62)
        at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:477)
        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:462)
        at net.minecraft.server.v1_5_R3.PlayerInteractManager.breakBlock(PlayerInteractManager.java:276)
        at net.minecraft.server.v1_5_R3.PlayerInteractManager.dig(PlayerInteractManager.java:125)
        at net.minecraft.server.v1_5_R3.PlayerConnection.a(PlayerConnection.java:547)
        at net.minecraft.server.v1_5_R3.Packet14BlockDig.handle(SourceFile:46)
        at net.minecraft.server.v1_5_R3.NetworkManager.b(NetworkManager.java:292)
        at net.minecraft.server.v1_5_R3.PlayerConnection.d(PlayerConnection.java:115)
        at net.minecraft.server.v1_5_R3.ServerConnection.b(SourceFile:35)
        at net.minecraft.server.v1_5_R3.DedicatedServerConnection.b(SourceFile:30)
        at net.minecraft.server.v1_5_R3.MinecraftServer.r(MinecraftServer.java:581)
        at net.minecraft.server.v1_5_R3.DedicatedServer.r(DedicatedServer.java:226)
        at net.minecraft.server.v1_5_R3.MinecraftServer.q(MinecraftServer.java:477)
        at net.minecraft.server.v1_5_R3.MinecraftServer.run(MinecraftServer.java:410)
        at net.minecraft.server.v1_5_R3.ThreadServerApplication.run(SourceFile:573)
    Caused by: java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
        at java.util.ArrayList$Itr.next(Unknown Source)
        at io.github.flaaghara.plugin.BlockSearchManager.addBlocks(BlockSearchManager.java:36)
        at io.github.flaaghara.plugin.BlockBreakEventListener.onBlockBreak(BlockBreakEventListener.java:21)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:425)
        ... 16 more
    The plugin is supposed to check for any blocks around each block in the ArrayList and if the the types are the same, it'll ad it to the ArrayList.
     
  2. Offline

    pt1448

    I'm assuming in your IDE there is correct tab spacing?
     
  3. Offline

    flaaghara

    pt1448 Yep, it just got messed up on the site.
     
  4. Offline

    bitWolfy

    flaaghara The error is obvious, yet tricky. You are trying to add an item into the list you are iterating over. Here's an easy fix:
    Code:java
    1. public void addBlocks() {
    2. for(Block block : new ArrayList<Block>(blockList)) {
    3. for(int x = -1; x <= 1; x++) {
    4. for(int y = -1; y <= 1; y++) {
    5. for(int z = -1; z <= 1; z++) {
    6. if(block.getRelative(x, y, z).getType() == block.getType()
    7. && !blockList.contains(block.getRelative(x, y, z)))
    8. blockList.add(block.getRelative(x, y, z));
    9. } } }
    10. }
    11. }

    Edit: Side note, you might want to store BlockState objects instead of entire Blocks. Safer that way...
     
  5. Offline

    flaaghara

    bitWolfy Just tested the code and it works! Thank you. Also why do you suggest BlockStates?
     
  6. Offline

    bitWolfy

    flaaghara No problem.
    As far as blocks and blockstates go, it depends on what you are trying to do. If you are fine with the fact that block's ID and data may change since the time you stored it, you should not have any real problems.
     
  7. Offline

    socram8888

    A bit offtopic: you might want to use a HashSet rather than an ArrayList:
    Code:
    HashSet<Block> blocks = new HashSet<Block>();
     
    public void addBlocks() {
        Iterator<Block> it = blocks.clone().iterator();
        while (it.hasNext()) {
            Block block = it.next();
            for(int x = -1; x <= 1; x++) {
            for(int y = -1; y <= 1; y++) {
            for(int z = -1; z <= 1; z++) {
                if(block.getRelative(x, y, z).getType() == block.getType())
                    blocks.add(block.getRelative(x, y, z));
            } } }
        }
    }
    Checking blockList.contains is slower, as it has to iterate through all components the list contains to check if it is already contained. When using a Set you don't have to worry about the list containing duplicates.
     
Thread Status:
Not open for further replies.

Share This Page