package tracematches; import java.util.*; public aspect FailSafeIterIndirection { pointcut collection_update(Collection c) : ( call(* java.util.Collection+.add*(..)) || call(* java.util.Collection+.remove*(..)) ) && target(c); tracematch(Collection c, Iterator i) { sym create_iter after returning(i) : call(* java.util.Collection+.iterator()) && target(c); sym call_next before: call(* java.util.Iterator+.next()) && target(i); sym update_source after : collection_update(c); create_iter call_next* update_source+ call_next { if(System.getProperty("TMTEST_ACTIVE")!=null) { throw new ConcurrentModificationException(); } } } static List l = new ArrayList(); public static void main(String[] args) { Runnable r = new Runnable() { public void run() { doSomething(); } }; //unsafe for (Iterator iter = l.iterator(); iter.hasNext();) { iter.next(); r.run(); } } public static void doSomething() { l.add(""); } }