10

According to the runtime error message the Exception occurs in the following line;

VirusData v = iteratorVirusDB.next();

VirusData is a class with a constructor and an overloaded constructor containing specific information about each of the viruses in the database such as;

  • String vName
  • String vDefinition

Overloaded with

  • Array with Tokenized definition (separated in groups of xLength)
  • Array with LCS Tokens
  • Float with a grade

iteratorVirusDB of type <VirusData> is an .iterator() of VirusDB, as shown bellow:

Iterator<VirusData> iteratorVirusDB = virusDB.iterator();

VirusDB is and ArrayList of type <VirusData> where I store the virus objects (name and def at this point) so that I can use them later.

ArrayList <VirusData> virusDB = new ArrayList<VirusData>();

And to end with, the error occurs in this method which uses all of the above explained:

private void selectDabataseMouseClicked(java.awt.event.MouseEvent evt) {
    while(iteratorVirusDB.hasNext()) {
        VirusData v = iteratorVirusDB.next();               //ERROR LINE
        String vSig = v.signature;                              
        v.tokens = tokenize.raw(vSig, true, tLength);
        ...
     }
     ...
}

I could really do with some help and advice on how to approach this problem in order to get get the program to run successfully. Bellow, the full StackTrace:

run:
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
        at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
        at java.util.AbstractList$Itr.next(AbstractList.java:343)
        at project_clean.Main.selectDabataseMouseClicked(Main.java:275)
        at project_clean.Main.access$100(Main.java:11)
        at project_clean.Main$2.mouseClicked(Main.java:76)
        at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:253)
        at java.awt.Component.processMouseEvent(Component.java:6270)
        at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
        at java.awt.Component.processEvent(Component.java:6032)
        at java.awt.Container.processEvent(Container.java:2041)
        at java.awt.Component.dispatchEventImpl(Component.java:4630)
        at java.awt.Container.dispatchEventImpl(Container.java:2099)
        at java.awt.Component.dispatchEvent(Component.java:4460)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4577)
        at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4247)
        at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
        at java.awt.Container.dispatchEventImpl(Container.java:2085)
        at java.awt.Window.dispatchEventImpl(Window.java:2478)
        at java.awt.Component.dispatchEvent(Component.java:4460)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Carlos
  • 5,405
  • 21
  • 68
  • 114
  • 1
    The iterator becomes invalid when you structurally modify the `ArrayList`. Saving an iterator as class state between members is suspect. Why are you doing that? – rlibby Feb 28 '11 at 18:46
  • I just answered a question regarding a ConcurrentModificationException... http://stackoverflow.com/questions/5145135/java-util-concurrentmodificationexception-on-arraylist/5145156#5145156 – John Vint Feb 28 '11 at 18:49
  • Well, I really do not know how iterators works I have just recently discovered they existed, so am pretty much just learning by trial and error. So if I understand you correctly i should not be doing this `Iterator iteratorVirusDB = virusDB.iterator();`? But then how can I iterate something like this; `VirusData v = virusDB.iterator().next();` ? Thanks for your suggestion – Carlos Feb 28 '11 at 18:54
  • Ah, please use copy+paste for your StackTrace, not a screenshot. – Paŭlo Ebermann Feb 28 '11 at 19:31

2 Answers2

12

The obvious explanation is that you have modified the virusDB in between calls. You mustn't modify the vector (except through the Iterator / ListIterator methods) while iterating using an iterator.

This snippet of code will always throw a ConcurrentModificationException:

import java.util.*;

class VirusData {
}

public class Test {

    public static void main(String[] args) {

        List<VirusData> list = new ArrayList<VirusData>() {{
            add(new VirusData());
            add(new VirusData());
            add(new VirusData());
        }};

        Iterator<VirusData> iterator = list.iterator();

        iterator.next();

        list.remove(0);
        VirusData s = iterator.next();
    }
}

From the documentation of ConcurrentModificationException:

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.

Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.

If your intention is to iterate through the entire database each time the method is called, I suggest you do

private void selectDabataseMouseClicked(java.awt.event.MouseEvent evt) {
    Iterator<VirusData> iteratorVirusDB = virusDB.iterator();
    while(iteratorVirusDB.hasNext()) {
        VirusData v = iteratorVirusDB.next();
        String vSig = v.signature;                              
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • but then if a program constantly modifies a list in this case, how can one iterate through it? – Carlos Feb 28 '11 at 19:05
  • 1
    You could use an index, `i`, replace `hasNext` with `i < yourList.size()` and `next()` with `yourList.get(i)`. – aioobe Feb 28 '11 at 19:09
  • Thanks so much aioobe, the suggestion you putted forward in your answer worked. However now am confused, when i do `v.tokens = tokenize.raw(vSig, true, tLength);` *(omited in your suggestion)* doesn't that violates the rule by modifying an element in the sequence. Or the term `modification` only applies to the collection "size", in order words only violates when adding / removing an item? – Carlos Feb 28 '11 at 19:21
  • 2
    The list doesn't care if the contents objects themselves are changing, it only cares when there are structural modifications, e.g. adding and removing elements, and maybe replacing an element with another one (`set(...)`, too - only these are modifications **of the list**. Of course, if you program is multithreaded, you should generally not modify your objects while using them in another thread, so use proper synchronization. – Paŭlo Ebermann Feb 28 '11 at 19:35
  • If you have two threads working on the same list and you are witnessing `ConcurrentModificationException`, then that means your operation is **not** thread safe and switching the style of iteration to avoid the exception may just lead to other, less expected exceptions. For example, once passing the `i < yourList.size()` check on the last element, then the other thread could remove any element before accessing it, and you'd cause an `IndexOutOfBoundsException`, which would probably make very little sense. To workaround this, make a copy of the array while iterating, or add synchronization. – pickypg Apr 21 '11 at 02:35
0

The concurrent modification exception occurs when you are modifying it while iterating over it at the same time. So check your code if you are modifying the list and it happens while you are iterating over it.

fastcodejava
  • 39,895
  • 28
  • 133
  • 186