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(); } }