最近,我遇到了导致ArrayIndexOutOfBoundsExceptionon的意外错误(不是我的代码)ArrayList#contains。此处的相关代码如下。
private static final List<String> list = new ArrayList<>();
static void register() {
update();
new Timer().schedule(new TimerTask() {
@Override
public void run() {
update();
}
}, 0, 21600000);
}
private static void update() {
list.clear();
new Thread(() -> {
List<String> other; //should always be the same length.
list.addAll(other);
}).start();
}
public static boolean contains(String string) { //called long after register
return list.contains(string); //throws ArrayIndexOutOfBounds
}
我很清楚这ArrayList不是线程安全的,可以使用来修复它Collections#synchronizedList。我的问题是了解此特定代码如何引发ArrayIndexOutOfBoundsException。
异常的stacktrace标识中的以下代码ArrayList#indexOf。
for (int i = 0; i < size; i++)
if (o.equals(elementData[i])) //here
return i;
在我看来,这只有在size大于时才会发生elementData.length。据我了解,ArrayList#clear实际上并没有减少支持数组的长度。到的调用addAll仅应增加其容量,并且size在扩展数组之后始终会对其进行更新。我看不到在size大于阵列容量的状态下怎么回事。
我注意到的一个特定细节是上的延迟Timer为0,这意味着update()快速连续调用了两次。我最好的猜测是,addAll调用在某种程度上是重叠的,这使列表成为某种混合的无效状态。
如果有人可以解释这里发生的事情,那就太好了!
相关分类