Java 是什么导致了这种异常?
我偶尔会遇到一个非常奇怪的例外: 04-18 18:08:08.121:E/AndroidRuntime(3031):未捕获处理程序:由于未捕获异常而退出主线程Java 是什么导致了这种异常?,java,android,exception,arraylist,Java,Android,Exception,Arraylist,我偶尔会遇到一个非常奇怪的例外: 04-18 18:08:08.121:E/AndroidRuntime(3031):未捕获处理程序:由于未捕获异常而退出主线程 04-18 18:08:08.141:E/AndroidRuntime(3031):java.lang.ArrayIndexOutOfBoundsException 04-18 18:08:08.141:E/AndroidRuntime(3031):在java.util.ArrayList.addAll(ArrayList.java:2
04-18 18:08:08.141:E/AndroidRuntime(3031):java.lang.ArrayIndexOutOfBoundsException
04-18 18:08:08.141:E/AndroidRuntime(3031):在java.util.ArrayList.addAll(ArrayList.java:257)
04-18 18:08:08.141:E/AndroidRuntime(3031):在com.zigzagworld.text.formatter.FormatManager.formatIfNeeded(FormatManager.java:185)
等等 这是在1.6模拟器上发生的。我的代码中调用
addAll
的行是:
mTasksAbove.addAll(schedule.above);
我唯一能想象的是对mTasksAbove
的某种并发访问。但是,我一直非常小心地确保在同一对象上同步所有访问。我唯一想到的另一件事是,如果在执行addAll
的过程中修改了上面的计划,但我相信这会生成ConcurrentModificationException
(另外,我认为我的代码不会这样做)。有人知道我还应该找什么吗
编辑
根据Raykud的回答,我做了一点挖掘,找到了确切的bug。在Android1.6源代码中,addAll
方法调用一个内部方法,growteand
,该方法存在缺陷。以下是来源本身:
private void growAtEnd(int required) {
int size = size();
if (firstIndex >= required - (array.length - lastIndex)) {
int newLast = lastIndex - firstIndex;
if (size > 0) {
System.arraycopy(array, firstIndex, array, 0, size);
int start = newLast < firstIndex ? firstIndex : newLast;
Arrays.fill(array, start, array.length, null);
}
firstIndex = 0;
lastIndex = newLast;
} else {
int increment = size / 2;
if (required > increment) {
increment = required;
}
if (increment < 12) {
increment = 12;
}
E[] newArray = newElementArray(size + increment);
if (size > 0) {
System.arraycopy(array, firstIndex, newArray, 0, size);
/********************************************************\
* BUG! The next 2 lines of code should be outside the if *
\********************************************************/
firstIndex = 0;
lastIndex = size;
}
array = newArray;
}
}
private void growtend(需要整数){
int size=size();
如果(firstIndex>=必需-(array.length-lastIndex)){
int newLast=lastIndex-firstIndex;
如果(大小>0){
System.arraycopy(数组,第一索引,数组,0,大小);
int start=newLast增量){
增量=所需;
}
如果(增量<12){
增量=12;
}
E[]newArray=newElementArray(大小+增量);
如果(大小>0){
System.arraycopy(数组,第一个索引,新数组,0,大小);
/********************************************************\
*BUG!接下来的2行代码应该在if之外*
\********************************************************/
firstIndex=0;
lastIndex=大小;
}
数组=新数组;
}
}
当列表先前已填充,然后清空时,该错误再次出现,留下size==0
和firstIndex==lastIndex>0
,您尝试添加一个足够大的集合,使其不适合lastIndex
和当前数组大小
从2.2开始,当addAll
方法被重写并且growtEnd
从类中消失时,bug就消失了
谢谢你,雷库德,你的指点 从1.5开始,arraylist中的addAll方法有缺陷,应该在将来的realease中修复,但是我不确定在哪个版本中。
为了解决这个问题,您可以为集合创建一个新的集合,并逐个添加元素。
下面是一些帮助您的代码:
Iterator<MyTypeofObjectToAdd> e = myArrayListToCopyFrom.iterator();
while (e.hasNext()) {
arrayListToAdd(e.next());
}
Iterator e=myArrayListToCopyFrom.Iterator();
while(e.hasNext()){
arrayListToAdd(例如next());
}
导致异常的原因是您试图从一个什么都没有的位置检索项目。什么是计划。上面的?我还认为这是一个同步问题-ArrayList.addAll()的源代码似乎是良性的,如果有的话,则是系统。arraycopy()引发异常。你能在每次通话前打印出schedule.over的大小以及mTasksAbove的当前大小和容量吗?实际上,你说你对mTasksAbove进行了细致的同步。上面的时间表呢?当您添加它时,会发生变化吗?@steveoh-schedule.above
也是一个ArrayList
@EboMike-我不同步访问schedule.above
,但是schedule
从一个方法返回,并传递给调用addAll
的代码。没有其他代码可以访问它。另外,更改不会导致addAll
中的迭代器出现ConcurrentModificationException
?我会研究打印列表的大小。谢谢你提供这些信息。令人不安的是,addAll
有bug。但是,这似乎与我的问题不太一样——null元素不会导致ArrayIndexOutOfBounds
异常(这是在调用addAll
时发生的,而不是在调用get()
时发生的)。我会试试你的方法,看看问题是否会消失。我已经确认有一个bug。从Android 2.2(API级别8)开始,它似乎已经消失了。再次感谢!