我遇到了非常奇怪的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();
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
以下异常被抛出:
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)
// ... //
Run Code Online (Sandbox Code Playgroud)
这段代码通常没有问题,已经生产了一年多.
这可能是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);
}
Run Code Online (Sandbox Code Playgroud)
下面的代码几乎每次运行时都会生成相同的异常 - 这个想法是在从另一个线程迭代时修改列表.对于(非)幸运时间,修改发生在方法checkForComodification之前但next = next.next;在ListItr#next方法之前,导致NPE.
javaapplication4.Test1.main中的java.util.LinkedList $ ListItr.next(LinkedList.java:891)中的线程"main"java.lang.NullPointerException中的异常(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();
}
}
Run Code Online (Sandbox Code Playgroud)
这是内部实施LinkedList.ListItr.next():
public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
lastReturned = next;
next = next.next; // your stacktrace says the NullPointerException happens here
nextIndex++;
return lastReturned.item;
}
Run Code Online (Sandbox Code Playgroud)
这NullPointerException是因为内部变量next是null; 但是,似乎hasNext()验证了下一个元素.
在我看来,这:
destroy()迭代列表的过程中修改列表.如果您使用destroy()@mthmulders的sugested 实现更新答案,我会更新,更正或删除我的答案.
| 归档时间: |
|
| 查看次数: |
3820 次 |
| 最近记录: |