package tracematches; import java.util.*; public class ASyncIteration { public static void main(String[] args) { final Collection c = new ArrayList(); Collection sc = Collections.synchronizedCollection(c); //this needs to stay synchronized (sc) { //this is ok but not recognized statically as such Iterator iter = sc.iterator(); System.err.println("ok"); } //this not Iterator iter = sc.iterator(); //this is ok final Collection c1 = new ArrayList(); Iterator iter1 = c1.iterator(); } /** * Tests a property mentioned in (see {@link Collections#synchronizedCollection(Collection)}), * which says that one should only iterate over a synchronized collection from within * a synchronized block. */ static aspect SyncCheck{ /* * Those tracechecks check that one does not directly access a Map or Collection * that has been put into Collections.synchronized*(..). */ pointcut createSync(): call(* Collections.synchr*(..)); //most common supertype of Map anc Collection is Object unfortunately tracematch(Object sync) { sym sync after returning(sync): createSync(); sym asyncIteration before: call(* Collection+.iterator()) && target(sync) && if(!Thread.holdsLock(sync)); sync asyncIteration { if(System.getProperty("TMTEST_ACTIVE")!=null) { throw new IllegalStateException("Collection "+System.identityHashCode(sync)+ " is synchronized. You may only iterate from within a synchronized block."); } } } } }