Java – nullpointer exception in LinkedList when using for each loop

I encountered very strange Java behavior. I don't know whether it is a bug or not

The code simply passes through the statestack (linked list) list and destroys all States

public void clearStates()
{
    LogFactory.getLog(StateController.class.getName())
      .info( "Clearing states. #ofstates="+stateStack.size());
    for (State state : stateStack)  // Line 132 (see exception)
    {
        state.destroy();
    }

    // ...
}

The following exception is thrown:

INFO  controllers.StateController : Clearing states. #ofstates=1
java.lang.NullPointerException\
    at java.util.LinkedList$ListItr.next(LinkedList.java:891)
    at *.controllers.StateController.clearStates(StateController.java:132)
    // ... //

This code usually has no problem and has been produced for more than a year

Could this be a Java bug?

/* update */

The destroy () call does not modify statestack If I think Java will throw concurrentmodificationexception

Statestack fills in a state that overrides destroy, but only local modifications Super implementation is better than printing additional logs ("destroy status..."), which is not in the log file, so I guess this exception is thrown at the beginning of the iteration

public void destroy()
{
    destroyed = true;
    LogFactory.getLog(State.class.getName()).info( "Destorying state : "+getClass().getName());
    propertyChangeSupport.firePropertyChange(PROP_DESTROYED,null,this);
}

Solution

The following code generates the same exception almost every time it runs - the idea is to modify the list while iterating from another thread Using (non) lucky time, the modification occurs after checkforconfirmation, but after next = next Before next; In the listitr#next method, NPE

public class Test {
    public static void main(String[] args) {
        final int SIZE = 100000;
        final Random rand = new Random();
        final List<Integer> list = new LinkedList<>();
        for (int i = 0; i < SIZE; i++) {
            list.add(i);
        }

        Runnable remove = new Runnable() {

            @Override
            public void run() {
                while (true) {
                    int i = rand.nextInt(SIZE);
                    list.remove(i);
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException ex) {
                        break;
                    }
                    list.add(i);
                }
            }
        };
        Thread t = new Thread(remove);
        t.start();
        for (int i = 0; i < 100; i++) {
            try {
                for (Integer j: list) {
                    ///whatever
                }
            } catch (ConcurrentModificationException e) {
            } catch (NullPointerException e) {
                e.printStackTrace();
            }
        }
        t.interrupt();
    }
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>