ConcurrentModificationException coming for CopyOnWriteArrayList as well [duplicate] - java

I'm occasionally getting a ConcurrentModificationException when I iterate over a list. A Google search informs me that it's probably because I'm altering that list in another thread while iterating over it and that to make this problem go away I should use java.util.concurrent.CopyOnWriteArrayList....
... except I already am.
Apparently, I'm doing something really stupid somewhere.
Does anybody have any insight into how one might induce CopyOnWriteArrayList to toss a ConcurrentModificationException? If it matters, I'm using Java 5.
Edit: Since the mutators I'm using may matter, I'm modifying this list in two ways:
Adding elements to the front. (list.add(0, newElement);)
Using subList to let older items fall off the back. (list = list.subList(0, MAX_LIST_SIZE);)
Do those raise red flags? If so, why? My understanding was that because these operations make a copy of the thing first, any existing iterators would be pointing at the unmodified original and would thus not care. Do I have a hole in my knowledge?
Edit 2: The precise code that's causing the problem is still a bit murky, but I can at least post the exception I'm seeing:
java.util.ConcurrentModificationException
at java.util.concurrent.CopyOnWriteArrayList$COWSubList.checkForComodification(Unknown Source)
at java.util.concurrent.CopyOnWriteArrayList$COWSubList.iterator(Unknown Source)
at....
... where it points to a for-each loop instantiation in my code.
That COWSubList does seem to imply that my call to subList is the root of my problem; I'd still like to understand why.
Edit 3: *facepalm*
CopyOnWriteArrayList.subList() returns a List, not a CopyOnWriteArrayList. The list it returns is under no implied obligation to provide any of COWAL's protections. Which makes using subList() like this to remove elements a Very Bad Idea.
Don't know for certain if this is my culprit, but it's damned suspicious and needs to be corrected regardless.

CopyOnWriteArrayList.subLists throw ConcurrentModificationExceptions if the containing list changes out from underneath it:
public class ListTest {
private static List<int[]> intList;
public static void main (String[] args) {
CopyOnWriteArrayList<Integer> cowal = new CopyOnWriteArrayList<Integer>();
cowal.add(1);
cowal.add(2);
cowal.add(3);
List<Integer> sub = cowal.subList(1, 2);
cowal.add(4);
sub.get(0); //throws ConcurrentModificationException
}
}

Sbodd has the correct answer, but it sounds like using CopyOnWriteArrayList instead of ArrayList is just an attempt to mask the error. The true problem is an attempt to modify the underlying list while iterating over it. You need to find where in your code you are accessing it as such and remove that usage or work around it.

Related

strange error in android java.util.ConcurrentModificationException

Hi guys I have a small problem. I'm writing a app for android and I have a part of my code like this.
public void loop(){
for(Car car:carList)
car.run();
}
I got the error java.util.ConcurrentModificationException
I also tried using iterators in order to solve the problem quickly.
Also, I use synchronized since I checked the error in oracle docs and it says that could be caused by many threads using the same code.
public synchronized void loop(){
Iterator<Car> carIterator = carList.iterator();
while(cardIterator.hasNext()){
carIterator.next().run();
}
}
I don't really know why any of the solutions I found didn't work. I use this portion of code most of the cases in a background service and I use it's class that contains that method (using singleton) in the acivity too.
Thanks in advance to all the comunity
Thanks for the support guys,
-carList is a ArrayList of Car objects.
my car class is like this
public class Car{
private int mSpeed;
private int mDistance; //zero at first
........
public void run(){
mSpeed=getRandomSpeed();
mDistance+=mSpeed;
updateDistanceInDB();//here I sabe the distance in DB using a DB helper
}
.........
}
-The error indicates that it's generated in the line that executes the method run
There's something strange because the app works well in another device I have.
The most brute-force way to fix this exception is to use a CopyOnWriteArrayList in place of your current List. This will ensure that any updates to the list during a for-each loop won't be seen during iteration, and therefore won't throw a ConcurrentModificationException.
According to its documentation:
The "snapshot" style iterator method uses a reference to the state of the array at the point that the iterator was created. This array never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException.
However, there may be a better way to solve your issue depending on the situation. Look for what parts of your code make modifications to the List, and ensure that they don't run during iteration.

Concurrent Modification Exception Cause by Painting?

I have been having a lot of trouble with the Concurrent Modification Exception error. With the help of the community I managed to fix my last error, however I think this error is more puzzling.
I am now getting a concurrent modification error while painting, I am worried that this error occurs in the paint function itself. Unlike my last error I am nto removing an entity, in that case I completely understood what was going on just not how to fix it, this error on the other hand I do not understand.
TowerItr = activeTowers.iterator();
while (TowerItr.hasNext()) {
try {
theTower = (ArcherTower) TowerItr.next();
g.drawImage(tower, theTower.y * Map.blockSize, theTower.x * Map.blockSize, this);
} catch (ConcurrentModificationException e) {
}
}
The line that throws the exception is this one:
theTower = (ArcherTower) TowerItr.next();
There are always two sides to a ConcurrentModificationException (CME), and only one side reports the error.
In this case, your code looks perfectly fine. You are looping through the members of the activeTowers.
The stack trace will show you nothing that you don't already know.... you have a CME.
What you need to find out is where you are adding/removing data from the activeTowers collection.
In many cases, there are reasonably easy fixes. A probable fix is to synchronize the access to the activeTowers array in every place it is used. This may be quite hard to do.
Another option is to use a collection from the java.util.concurrent.* package, and to use the toArray(...) methods to get a snapshot of the collection, and then you can iterate that snapshot in your while loop.
// activeTower must be something from java.util.concurrent.*
for (ArcherTower theTower : activeTower.toArray(new ArcherTower[0]) {
g.drawImage(tower, theTower.y * Map.blockSize, theTower.x * Map.blockSize, this);
}
I should add that if you use a java.util.concurrent.* collection, then the iterator() will return a 'stable' iterator too (will not throw CME, and may (or may not) reflect changes in the collection)
Bottom line is that a CME only tells you half the story.... and only your code will tell you the rest....
Carrying on from what our esteemed members have suggested:
1) This error is generally seen when the List is being modified after an Iterator has been extracted.
2) I am looking at your code and it seems alright except this being used in the drawImage() method. This may potentially be altering your List because This has direct access to class members / class variables.
3) This can also happen if multiple threads are accessing the List concurrently. And one of the threads may be trying to alter your List from some other method which share the same instance of the List. I am saying some other method because concurrent read access should not create trouble if multiple threads were accessing this method.
Note: Please all posible code and Stake trace to debug exact problem.

ArrayList.addAll(ArrayList) throws SOMETIMES UnsupportedOperationException

I have a code that read list from some paged string data. What I do not understand - why the UnsupportedOperationException is thrown on addAll() and why it's kind of random behaviour ?
I know creating target ArrayList and not adding to the returned one solves the issue, I'm looking for better understanding not a fix.
List<Event> eventList = eventTable.getEvents(); // returns ArrayList
while (hasNextPage()) {
goToNextPage();
eventList.addAll(eventTable.getEvents());
}
List<Event> is not necessarily an ArrayList<Event>. (The opposite is true though.)
The reason you get UnsupportedOperationException sometimes, is because eventTable.getEvents() sometimes returns a list that supports addAll and sometimes it doesn't.
The implementation of getEvents could for instance look like this:
if (noEventsAvailable) {
return Collections.emptyList();
} else {
List<Event> toReturn = new ArrayList<Event>();
// populate list...
return toReturn;
}
(In your comment you write // returns ArrayList. I don't know where you've got this from, but I know one thing for sure: An ArrayList will always support the addAll operation.)
The correct way to solve it is, as you mention, to do
List<Event> eventList = new ArrayList<Event>(eventTable.getEvents());
It depends on the actual implementation of List.
e.g if the underlying list was obtained using Collections.unmodifiableList() then calling addAll() or any other modification method will throw an UnsupportedOperationException.
When it throws an exception, it should show you the exact line number and source code file - you should be able to find out exactly why it's throwing an exception.
My guess is that under certain circumstances, eventTable.getEvents() returns an immutable list, or something like that - but without knowing what eventTable is, it's hard to say for sure. If you can produce a short but complete program which demonstrates the problem, that would make it a lot easier to diagnose.

I get the following exception: "java.util.ConcurrentModificationException"

I'm getting a "An exception occurred: java.util.ConcurrentModificationException" when I run this piece of code. Does anyone here see what the problem is?
public void mudaDeEstado() {
Luz luz = new Luz();
while(this.iterador.hasNext()) {
luz = (this.iterador.next());
luz.defineEstado(!luz.acesa());
}
}
Thanks a lot!!
You are trying to modify the reference that the iterator holds while looping through the elements. You can read more about his exception here.
For example, it is not generally
permissible for one thread to modify a
Collection while another thread is
iterating over it. In general, the
results of the iteration are undefined
under these circumstances. Some
Iterator implementations (including
those of all the general purpose
collection implementations provided by
the JRE) may choose to throw this
exception if this behavior is
detected. Iterators that do this are
known as fail-fast iterators, as they
fail quickly and cleanly, rather that
risking arbitrary, non-deterministic
behavior at an undetermined time in
the future.
Most probably the culprit here is this:
luz.defineEstado(!luz.acesa());
This exception is thrown when you modify a data structure while you are iterating through it. Changing the elements in the data structure can change the way one iterates through the elements, so many data structures do not allow concurrent modification.
Try keeping a list of elements that need to be updated and then go back through and update those elements once you have iterated through the entire data structure.
Sorry my wording is kind of general and ambiguous, but it's hard to give specifics with the provided code.

CopyOnWriteArrayList throwing CurrentModificationException

I'm occasionally getting a ConcurrentModificationException when I iterate over a list. A Google search informs me that it's probably because I'm altering that list in another thread while iterating over it and that to make this problem go away I should use java.util.concurrent.CopyOnWriteArrayList....
... except I already am.
Apparently, I'm doing something really stupid somewhere.
Does anybody have any insight into how one might induce CopyOnWriteArrayList to toss a ConcurrentModificationException? If it matters, I'm using Java 5.
Edit: Since the mutators I'm using may matter, I'm modifying this list in two ways:
Adding elements to the front. (list.add(0, newElement);)
Using subList to let older items fall off the back. (list = list.subList(0, MAX_LIST_SIZE);)
Do those raise red flags? If so, why? My understanding was that because these operations make a copy of the thing first, any existing iterators would be pointing at the unmodified original and would thus not care. Do I have a hole in my knowledge?
Edit 2: The precise code that's causing the problem is still a bit murky, but I can at least post the exception I'm seeing:
java.util.ConcurrentModificationException
at java.util.concurrent.CopyOnWriteArrayList$COWSubList.checkForComodification(Unknown Source)
at java.util.concurrent.CopyOnWriteArrayList$COWSubList.iterator(Unknown Source)
at....
... where it points to a for-each loop instantiation in my code.
That COWSubList does seem to imply that my call to subList is the root of my problem; I'd still like to understand why.
Edit 3: *facepalm*
CopyOnWriteArrayList.subList() returns a List, not a CopyOnWriteArrayList. The list it returns is under no implied obligation to provide any of COWAL's protections. Which makes using subList() like this to remove elements a Very Bad Idea.
Don't know for certain if this is my culprit, but it's damned suspicious and needs to be corrected regardless.
CopyOnWriteArrayList.subLists throw ConcurrentModificationExceptions if the containing list changes out from underneath it:
public class ListTest {
private static List<int[]> intList;
public static void main (String[] args) {
CopyOnWriteArrayList<Integer> cowal = new CopyOnWriteArrayList<Integer>();
cowal.add(1);
cowal.add(2);
cowal.add(3);
List<Integer> sub = cowal.subList(1, 2);
cowal.add(4);
sub.get(0); //throws ConcurrentModificationException
}
}
Sbodd has the correct answer, but it sounds like using CopyOnWriteArrayList instead of ArrayList is just an attempt to mask the error. The true problem is an attempt to modify the underlying list while iterating over it. You need to find where in your code you are accessing it as such and remove that usage or work around it.

Categories

Resources