com.arsdigita.developersupport
Class Comodifications

java.lang.Object
  extended bycom.arsdigita.developersupport.Comodifications

public final class Comodifications
extends Object

Provides tools for debugging concurrent modification exceptions that may occur in multi-threaded programs. This class should be used for debugging only.

Let's illustrate by example. A concurrent modification exception will occur if you call Iterator.next() on an iterator whose underlying collection has changed after the iterator was created. Here's the simplest example:

 import java.util.*;
 
 public final class CoMoExample {
     public final static void main(String[] s) {
         List list = new LinkedList();
         list.add("foo");
         for (Iterator it=list.iterator(); it.hasNext(); ) {
             System.out.println(it.next());
             list.add("bar");
         }
     }
 }
 

If you compile CoMoExample.java and run it, you'll get something like this:

 $ java -cp . CoMoExample
 foo
 Exception in thread "main" java.util.ConcurrentModificationException
         at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:530)
         at java.util.LinkedList$ListItr.next(LinkedList.java:471)
         at CoMoExample.main(CoMoExample.java:8)
 

In this case, the program is single-threaded and the source of the concurrent modification exception is trivially discernible. Things get more complicated when you have two threads, one of which is iterating over a collection, while the other is concurrently modifying the same collection. You will get a ConcurrentModificationException similar to the above, but it only gives you one half of the picture. It shows what the iterating thread was doing when the comodification was detected. It doesn't show you the other thread that was modifying the shared collection concurrently.

If you have a reproducible case of concurrent modification, you can debug it by instrumenting the offending collection as follows. Say, the culprit collection is a list, allocated like so:

 List culprit = new LinkedList();
 

You may edit the above piece of code like so:

 List culprit = Comodifications.newUnforgetfulList(new LinkedList());
 

This will give an "instrumented" list that tracks concurrent modifications a lot better than your standard list. When a concurrent modification occurs, the following stack traces will be logged.

  1. The point where the offending iterator was created. Something like this:

     The iterator was created at
     StackTrace: [thread 19; timestamp=15:02:47.439]
             at Comodifications$ListHandler$IteratorImpl.(Comodifications.java:112)
             at Comodifications$ListHandler.invoke(Comodifications.java:72)
             at $Proxy0.iterator(Unknown Source)
             at Main$Page.dispatch(Main.java:63)
     
  2. The point where the other thread comodified the shared list.

     Comodification occurred at
     StackTrace: [thread 20; timestamp=15:02:47.459]
             at Comodifications$ListHandler.invoke(Comodifications.java:78)
             at $Proxy0.add(Unknown Source)
             at Main$Page.init(Main.java:56)
     

Note that the "instrumented" list returned by newUnforgetfulList(List) captures a stack trace every time the list is mutated. This may noticeably slow down all mutator methods and change the timing, thereby accidentally eliminating the race condition are you are trying to debug.

Since:
2003-12-22
Version:
$Id: //core-platform/dev/src/com/arsdigita/developersupport/Comodifications.java#4 $
Author:
Vadim Nasardinov (vadimn@redhat.com)
See Also:
StackTrace

Method Summary
static List newUnforgetfulList(List list)
          Wraps the passed in list inside a tracking proxy list.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Method Detail

newUnforgetfulList

public static List newUnforgetfulList(List list)
Wraps the passed in list inside a tracking proxy list. The returned proxy list provides better error reporting for concurrent modification exceptions.



Copyright (c) 2004 Red Hat, Inc. Corporation. All Rights Reserved. Generated at July 20 2004:2337 UTC