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