3

I have a problem. Accessing to a Vector concurrently I get an ConcurrentModificationException. I added synchronized blocks to all the vector iterations but maybe forgot one or there is another leak.

The problem is that the in error stacktrace the error shown is a call to Vector.retainAll() which is a synchronized method. How can I guess whats the other point involved in the collision?

Thanks in advance

 08-24 13:37:25.968: ERROR/AndroidRuntime(6582): java.util.ConcurrentModificationException
 08-24 13:37:25.968: ERROR/AndroidRuntime(6582):     at java.util.AbstractList$SubAbstractList.listIterator(AbstractList.java:320)
 08-24 13:37:25.968: ERROR/AndroidRuntime(6582):     at java.util.AbstractList$SubAbstractList.iterator(AbstractList.java:307)
 08-24 13:37:25.968: ERROR/AndroidRuntime(6582):     at java.util.AbstractCollection.contains(AbstractCollection.java:128)
 08-24 13:37:25.968: ERROR/AndroidRuntime(6582):     at java.util.Collections$SynchronizedCollection.contains(Collections.java:432)
 08-24 13:37:25.968: ERROR/AndroidRuntime(6582):     at java.util.AbstractCollection.retainAll(AbstractCollection.java:319)
 08-24 13:37:25.968: ERROR/AndroidRuntime(6582):     at java.util.Vector.retainAll(Vector.java:856)
Addev
  • 31,819
  • 51
  • 183
  • 302
  • Collection#SynchronizedCollection won't lock the backed collection while iterate it. read [the documentation](http://download.oracle.com/javase/7/docs/api/java/util/Collections.html#synchronizedCollection%28java.util.Collection%29) – Prince John Wesley Aug 24 '11 at 11:51

2 Answers2

4

Check for a code where you structurally modify Vector (add or remove) while iterating it - this is most likely reason why you're getting CME. Use iterator to do such a modification to avoid CME

void unsafeMod(Vector data) {
    for (Object o : data) {
        if (o != null) {
            data.remove(o); // may cause CME
        }
    }
}

Also I second an advice to use ArrayList instead of Vector.

Community
  • 1
  • 1
gnat
  • 6,213
  • 108
  • 53
  • 73
  • 1
    Actually, it is the only way to get a CME. The fact that multiple threads may be involved doesn't change that. Similar, but not an exact duplicate of this one http://stackoverflow.com/questions/602636/concurrentmodificationexception-and-a-hashmap/602660#602660 – Robin Aug 24 '11 at 13:16
1

Just don't let anyone else (than the object holding the vector) access the vector. This is the only way to make sure that nobody other than the holding object modifies it while iterating on it.

Return and pass copies of the vector from the methods of the holding object, or return/pass an unmodifiable version (using Collections.unmodifiableList()). Returning an unmodifiable list will break the code doing the retainAll call, of course.

Side note: Vector is obsolete and should not be used anymore. As you just noticed, the fact that it's synchronized doesn't shield you from concurrent access bugs. So using an ArrayList is better.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • My apologies, I originally downvoted because the CME is not specifically a threading related issue and I was going to comment to that effect. After looking at the question more closely and realizing the error occurred within the retainAll() method, I realized that in this case it is a threading issue, unfortunately I am unable to alter my vote since too much time had passed. – Robin Aug 24 '11 at 13:31