首页 > 解决方案 > 不应该发生的 java.lang.ArrayIndexOutOfBoundsException

问题描述

Crashlytics 和 Google Play 控制台都为我的至少两个用户报告了此崩溃。

致命异常:java.lang.ArrayIndexOutOfBoundsException:长度=10;指数=-1

在 java.util.ArrayList.get(ArrayList.java:413)

这是导致它的行:

if (savedState.userEntries.size() > 0 && savedState.userEntries.get(savedState.userEntries.size()-1).getDuration()==0)

那种崩溃不是不可能的吗? getDuration()只是一个返回整数的getter。

标签: java

解决方案


那种崩溃不是不可能的吗?

如果有另一个线程修改ArrayList.

例如:

if (
    (savedState.userEntries.size()>0) && 
    // Another thread empties the list NOW
    (savedState.userEntries.get(savedState.userEntries.size()-1).getDuration()==0)
) {

如果可以从多个线程访问和修改这些数据结构,那么:

  • 它应该使用的所有操作synchronized或其他一些锁定以确保线程安全,或者
  • 数组列表应替换为并发数据结构。

您需要根据对当前数据结构使用方式的总体评估在方法之间进行选择。例如,您可能希望将其替换为Queue.

(一些潜在的解决方案将不起作用;例如,替换ArrayListwithsynchronizedList(list)在这里不起作用,因为您在这里执行 2 个列表操作(size& get),这些操作需要作为原子操作执行。)


你表示怀疑:

我不知道。理论上它可以改变,但如果它在两天内发生在两个用户身上,并且在这些评估之间的时间内,它似乎极不可能。

  1. 极不可能的事件确实发生了。

  2. 您对“极不可能”的直觉可能是错误的(基于证据!)。除非您进行彻底的数学分析(或大量测量),否则您实际上无法量化“极不可能”的概率。

  3. 概率可能会受到您使用软件的方式、平台行为的差异/变化等的影响。

  4. 你有证据支持的替代解释吗?

  5. 一个有经验的程序员(并发)会认识到这是一个潜在的原因,并且无论如何都要修复它,不管他/她对可能性的直觉。


推荐阅读