我遇到了非常奇怪的
Java行为,我不知道它是不是一个bug,或者
我错过了什么.
我错过了什么.
代码只是通过stateStack(LinkedList)列表并销毁所有状态.
public void clearStates() { LogFactory.getLog(StateController.class.getName()) .info( "Clearing states. #ofstates="+stateStack.size()); for (State state : stateStack) // Line 132 (see exception) { state.destroy(); } // ... }
以下异常被抛出:
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) // ... //
这段代码通常没有问题,已经生产了一年多.
这可能是Java bug吗?
/ *更新* /
destroy()调用不会修改stateStack.如果我认为Java会
抛出ConcurrentModificationException.
stateStack填充了1个状态,它覆盖了destroy,但只是覆盖了
当地的修改.超级实现比打印额外的日志(“销毁状态……”),这不在日志文件中,所以我猜这个异常被抛出
迭代的开始.
public void destroy() { destroyed = true; LogFactory.getLog(State.class.getName()).info( "Destorying state : "+getClass().getName()); propertyChangeSupport.firePropertyChange(PROP_DESTROYED,null,this); }
解决方法
下面的代码几乎每次运行时都会生成相同的异常 – 这个想法是在从另一个线程迭代时修改列表.使用(非)幸运时间,修改发生在checkForComodification之后但在next = next.next之前;在ListItr#next方法中,导致NPE.
Exception in thread “main” java.lang.NullPointerException
at java.util.LinkedList$ListItr.next(LinkedList.java:891)
at javaapplication4.Test1.main(Test1.java:74)
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(); } }