Using annotations to specify target CLASS and METHOD
adinn Feb 3, 2010 7:32 AMWhile looking at AOP in the last few days I noted that the pointcut notation allows target classes, methods and fields to be specified using annotations in place of class, method or field names. I wondered if there might not be a similarly useful feature that could be included in Byteman rules e.g.
RULE annotation example
CLASS @org.my.ClassTag
METHOD @org.my.MethodTag
HELPER org.my.TagHelper
IF TRUE
DO helpMe($0)
ENDRULE
Of course, this presents one or two issues. Here are some initial questions and possibel answers.
Firstly, what are the implications of making references to method parameters such as $0, $1 etc in the absence of a specific class or method?
These are not actually resolved at trigger injection time anyway. So, an inappropriate parameter reference would merely raise a type exception at first triggering and disable the rule e..g if helpMe expects an org.my.Foo and the rule is applied to a tagged class other than Foo or its subclasses then a type error ensues. There is nothign to stop method annotations being used in conjunction with a signature, thereby ensuring that triggering is only enabled for methods with the requisite matching parameter types e.g.
METHOD @org.my.MethodTag(Foo, Bar)
This helps but does not resolve the issue regarding $0. It might be possible to combine the CLASS annotation with a specific type for the target class e.g.
CLASS @org.my.ClassTag Foo
meaning only apply the rule to a class with name Foo if it is annotated. More usefully,
CLASS @org.my.ClassTag ^Foo
would apply to Foo or any of its subclasses. Note that with this extended notation the original bare annotation is simply an abbreviated version of the equivalent specification
CLASS @org.my.ClassTag ^Object
It is debatable whether the case where the ^ notation is omitted is really useful since in any given application the class Foo either will or will not be annotated. Perhaps, inlcusion of ^ should not be required and the unadorned class should be used as the maximal type for the classes considered for injection rather than an exact match i.e. we dro pthe first case and implement the second case without the need for the ^.
Secondly, what does this require the transformer and retransformer to do in order to be able to identify the relevant target classes/methods and ensure that the rule code gets injected where specified.
Using an annotation for the CLASS specifier requires checking every class as it is loaded which will make transformation slower in all cases -- but probably no worse than is already implied by using injection down class hierarchies. SImilarly, it will require checking all existing loaded classes for annotations during retransformation when a rule with a class annoation is first installed either during bootstrap or during dynamic load via the listener. This is probably a lot more work -- although this might be mitigated by using a cache of some sort.
Annotations on methods make this cost greater still by requiring a more thorough scan of class bytecode during load and requiring a larger cache and more complex cache index to track annotations already identified on loaded classes.
Is this complexity worth whatever gains this feature provides? I'm not yet convinced
Note there is also a chance to do a similar sort of thing with AT READ @Foo and @WRITE @Foo