0

Both Crashlytics and Google Play console report this crash for at least two of my users.

Fatal Exception: java.lang.ArrayIndexOutOfBoundsException: length=10; index=-1

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

Here's the line that supposedly caused it:

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

Shouldn't that crash be impossible? getDuration() is just a getter that returns an integer.

Community
  • 1
  • 1
TimSim
  • 3,936
  • 7
  • 46
  • 83
  • 1
    Come on, man. You should know how to ask a question. Read [ask] and provide a [mcve]. – RaminS Mar 13 '19 at 22:19
  • Well it's not verifiable, that's the problem. – TimSim Mar 13 '19 at 22:20
  • 1
    `savedState.userEntries.size()` changes between the three evaluations? – Andy Turner Mar 13 '19 at 22:22
  • I don't know. It can change theoretically but if it happened to two users in two days and within the time between those evaluations, it just seems extremely unlikely. – TimSim Mar 13 '19 at 22:24
  • What about a concurrency problem? Are there other threads modifying the ArrayList? – Donat Mar 13 '19 at 22:25
  • So you have another thread making changes to this arraylist? read the documentation: "Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally." – Nathan Hughes Mar 13 '19 at 22:25
  • Are you sure it is this line that caused it and not something inside the if clause? – RaminS Mar 13 '19 at 22:25
  • I have ~4k daily users and this has never been reported in the 4 years the app's been available. But yes, this list is being modified in another thread but I had no idea it could be an issue when there are two evaluations right after another in the same statement. And it doesn't look like a freak accident either given that it's been reported twice. – TimSim Mar 13 '19 at 22:33
  • 3
    there's a quote in the preface of Java Concurrency In Practice : "most Java programs are so rife with concurrency bugs that they work only by accident"; this is the kind of thing it's talking about. – Nathan Hughes Mar 13 '19 at 22:37

1 Answers1

3

Shouldn't that crash be impossible?

It is not impossible if there is another thread modifying the ArrayList.

For example:

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

If these data structures could possibly be accessed and modified from more than one thread, then either:

  • all operations it should use synchronized or some other locking to ensure thread-safety, or
  • the array list should be replaced with a concurrent data structure.

You need to choose between the approaches based on an overall assessment of how the current data structure is used. For example, you may want to replace it with a Queue.

(Some potential solutions won't work; e.g. replacing ArrayList with synchronizedList(list) won't work here because you are doing 2 list operations here (size & get) that need to be performed as an atomic operation.)


You express doubts:

I don't know. It can change theoretically but if it happened to two users in two days and within the time between those evaluations, it just seems extremely unlikely.

  1. Extremely unlikely events do happen.

  2. Your intuition about "extremely unlikely" is probably wrong (based on the evidence!). Unless you do a thorough mathematical analysis (or lots of measurements) you can't actually quantify the probability of "extremely unlikely".

  3. The probabilities can be affected by how you softeare is used, differences / changes in platform behavior ans so on.

  4. Do you have an alternative explanation supported by evidence?

  5. An experienced programmer (in concurrency) would recognize this as a potential cause, and fix it anyway, irrespective of his / her gut feeling of likelihood.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Or he could just use a threadsafe arraylist. https://stackoverflow.com/questions/2444005/how-do-i-make-my-arraylist-thread-safe-another-approach-to-problem-in-java –  Mar 13 '19 at 22:38
  • yea ... hit post by accident :-) – Stephen C Mar 13 '19 at 22:39