package tracematches; import java.util.*; public aspect FailSafeIterDeadCode { 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(); } } } public static void main(String[] args) { final List l = new ArrayList(); //safe for (Iterator iter = l.iterator(); iter.hasNext();) { iter.next(); } new Runnable() { //this is never called, so it will be abstracted away public void run() { l.add(""); } }; } }