简体   繁体   中英

Java - Index Out Of Bounds Exception: Index: 1, Size: 2

While working on some java project I encountered this peculiar error:

java.lang.IndexOutOfBoundsException: Index: 1, Size: 2

How can there be an index out of bounds exception? Index 1 means it tries to get the second element, Size 2 means there are 2 elements, so there shouldn't be a problem, no?

Context:

I have the following function:

public int howManyAgents(){
    // cell is a class that can have 0 or multiple objects
    // I get a list of cells that contain at least 1 agent
    List<Cell> cellsWithAgents = getNonEmptyCells();

    // initializing a counter
    int agentsCount = 0;

    for(int i=0; i<cellsWithAgents.size(); i++){

        // For every cell in the list I add to the counter the number of       
        // agents that cell contains
        agentsCount += cellsWithAgents.get(i).howManyAgents();
    }
    return agentsCount;
}

Now, the problem was that I got a null pointer exception at the line:

agentsCount += cellsWithAgents.get(i).howManyAgents();

I want to debug the code, but this function is called many times while the program is running and the null pointer exceptions comes up at different points in time (after 10 seconds after 1 minute after 5 minutes). So I tried to come up with a method to have e breakpoint when the cell is null so I came up with this code:

public int howManyAgents(){
    // cell is a class that can have 0 or multiple objects
    // I get a list of cells that contain at least 1 agent
    List<Cell> cellsWithAgents = getNonEmptyCells();

    // initializing a counter
    int agentsCount = 0;

    for(int i=0; i<cellsWithAgents.size(); i++){

        int pass;
        if (null == cellsWithAgents.get(i))
            pass = 1; // breakpoint here

        // For every cell in the list I add to the counter the number of       
        // agents that cell contains
        agentsCount += cellsWithAgents.get(i).howManyAgents();
    }
    return agentsCount;
}

Of course, it is not the best method. The most logical way is jut to surround the code with try/catch and put the breakpoint there. The point is that the code above didn't work. It did not stop at the breakpoint but instead it threw the index out of bounds exceptions at the line:

if (null == cellsWithAgents.get(i))

Why? How can it be possible to throw an index out of bound exception if apparently the index is in bounds?

Edit: changed a mistake in copying the code

Update: I have tried to see why the null pointer exception appears with a try/catch and put a breakpoint there. It seems that cellsWithAgents sometimes contains a null. This is, most probably because of concurrency as @rlinden stated.

About concurrency: there are some cells that can contain agents. There is a variable number of agents that can move between the cells. There is a special agent that tries to count how many moving agents there are (using this function). So, only one agent (thread) can use this function, but multiple agents can modify cells (and thus mess with getNonEmptyCells() and howManyAgents() results).

Still, how it is possible to get index out of bounds with size 2 and index 1? It is not possible because of the concurrency, is it? Because only this thread can change the list cellsWithAgents. So, even if one of the elements in the list becomes null, the list still contains that number of pointers, so the size of the list cannot change. Or can it in some way that I miss? And how can it be explained that the stack trace prints Index:1 Size: 2?

New Idea

Try changing the loop and see if the error persists:

int agentsCount = 0;
for(Cell cell : getNonEmptyCells()) {
    if(cell != null) {
       agentsCount += cell.howManyAgents();
    } else {
       System.out.println("Found a null cell");
    }
}

I would like to see the code of the method getNonEmptyCells() . If your program is actually multithreaded and this function returns a fixed List that is changed at every interaction, then it is possible that changes in following executions have affected the previous, unfinished ones.

This is due to the fact that the line cellsWithAgents = getNonEmptyCells(); does not create a copy, but a reference to the return value of getNonEmptyCells() . So, if this method reuses the return object, it is possible that the first execution would believe there was two, but the concomitant thread changed the content size to less than 2.

The problem is, program is throwing exception at cellsWithType.get(i) . What you can do is either put a breakpoint at if (null == cellsWithType.get(i)) and try debug it. Or change it to,

if (i >= cellsWithType.size())
        pass = 1; // breakpoint here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM