import java.util.*; public aspect FailSafeEnumThread { pointcut vector_update() : call(* Vector.add*(..)) || call(* Vector.clear()) || call(* Vector.insertElementAt(..)) || call(* Vector.remove*(..)) || call(* Vector.retainAll(..)) || call(* Vector.set*(..)); tracematch(Vector ds, Enumeration e) { sym create_enum after returning(e) : (call(* Vector+.elements()) && target(ds)) || (call(Enumeration+.new(..)) && args(ds)); sym call_next before : call(Object Enumeration.nextElement()) && target(e); sym update_source after : vector_update() && target(ds); create_enum call_next* update_source+ call_next { } } public static void main(String[] args) { //safe c1.add(""); //safe but not recognized because enumerations are collapsed Enumeration e = c1.elements(); e.nextElement(); thread(); //this thread may modify c1 any time foo(); //this method iterates over c1; this may cause an exception when //interleaved badly with the thread } static final Vector c1 = new Vector(); static final Vector c2 = new Vector(); static void foo() { Enumeration e = c1.elements(); e.nextElement(); } static void thread() { new Thread() { public void run() { c1.add("");//this has to stay Vector v = new Vector(); Enumeration en = v.elements(); en.nextElement(); v.add(""); } }.start(); } }