import java.util.*; public aspect AB { static Test unnecessary = new Test(); static Test cannotTriggerFinal = new Test(); static Test cannotTriggerFinal2 = new Test(); static Test canPartiallyTriggerFinal = new Test(); static Test shadowMotion = new Test(); static Test shadowMotionRedef = new Test(); static int x; tracematch(Object o) { sym a before: call(* *.a()) && target(o); sym b before: call(* *.b()) && target(o); sym x before: call(* *.x()) && target(o); a+ b { } } //all shadows here remain, except the ones tagged public static void main(String[] args) { unnecessary.b(); unnecessary.a(); unnecessary.x(); unnecessaryShadows1(); unnecessaryShadows2(); cannotTriggerFinal(); cannotTriggerFinal2(); cannotTriggerFinal2.b();//removed by flow-ins canTriggerFinal(); canTriggerFinal2(); canPartiallyTriggerFinal(); shadowMotion.b(); shadowMotionRedef.b(); shadowMotion(); shadowMotionInnerLoopRedef(); noShadowMotion(); } static void unnecessaryShadows1() { Test u = unnecessary; u.a();//necessary u.a();//unnecessary u.a();//unnecessary } static void unnecessaryShadows2() { Test u = unnecessary; u.a();//necessary u.a();//unnecessary u.a();//unnecessary u.b();//necessary } static void cannotTriggerFinal() { Test c = cannotTriggerFinal; while("".length()>2) { c.x();//cannot trigger final c.b();//unnecessary } c.x();//cannot trigger final } static void canTriggerFinal() { cannotTriggerFinal.a();//2nd flowins or cannot trigger final, depending on analysis order } static void canTriggerFinal2() { cannotTriggerFinal.x();//removed by flowins. only } static void shadowMotion() { Test s = shadowMotion; while(s.a()) {//moved by sm s.x();//removed by sm } } static void shadowMotionInnerLoopRedef() { int i = 5; while(i>0) { Test s = shadowMotionRedef; //not that s is redefined in the outer loop while(s.a()) {//yet... moved by sm s.x();//removed by sm } i--; } } static void noShadowMotion() { Test s = shadowMotion; while(s.a()) {//cannot be moved s = shadowMotion;//value of shadowMotion might have changed s.x();//cannot be moved } } static class Test { boolean a() {return new String().equals("");} void b() {} void x() {} } }