Download presentation
Presentation is loading. Please wait.
1
Advice Weaving in AspectJ Alex Gontmakher
2
Outline Possible implementation approaches Quick JVM primer AJC implementation Performance Evaluation
3
Approaches to Aspect code generation Change the VM to recognize aspects Compile-time weaving of aspects Load-time weaving Reflection
4
Changing the VM Can provide full support for all Aspect features Data for aspects separate from the code Not portable (generated code is not Java bytecode) Problems with the reference Java implementation Hard to make changes to Java standard Hard to evolve AspectJ implementation
5
Load-time weaving Modify the code during loading Probably can be done Same benefits as with VM-supported aspects Potentially slow Trade-Off between load-time and run-time Expensive to do static analysis (optimization)
6
Compile time code generation Portable Fast Necessarily limited
7
Compile-time code generation: The problem before(): get(int Point.x) { System.out.println(“get x”); } Compiler doesn't see all the code Code that is dynamically loaded Code that is called through reflection
8
Compile-time code generation: Solution AspectJ solution: aspects apply only to code that the implementation controls Loosely speaking: all the bytecode available at compile time Can change between implementations and versions
9
Compile-time code generation: The limitations Advice on field access Accessor code must be available Advice on method and constructor call Calling code must be available Advice on method execution The method code must be available Etc. Limitations not met Compile time error!
10
Part 2: JVM Primer
11
Java Virtual Machine: structure Frame 0 Frame 1 Frame 2 SP Stack (per thread) Constant Pool Class Hello method: print() method: () Class Main method: main() method: () field: int fM String “hello world” Frame 2 locals: this int i int j Param stack: System.out String … Class: Frame 1 locals: this … Param stack: Hello … Class: Heap Object Hello field: int f1 field: String f2
12
JVM primer: instructions 1 Arithmetic Instructions take inputs from param stack, write results back Getting values to and from local vars Getting values to and from objects Method calls and returns Exception handling Etc.
13
JVM Primer: instructions 2 Arithmetic instructions iadd: …, value1, value2 …, value1+value2 Load and store local variables iload VAR: … …, iload_ : … …, istore VAR: …, value … {VAR = value} istore_ : …, value … {VAR_n = value} Stack manipulation dup: …, value …, value, value
14
JVM primer: instructions 3 Object access Accessing object’s fields: getfield, putfield getfield FID: …, objectref …, value putfield FID: …, value, objectref … Accessing object’s static fields: getstatic, putstatic getstatic FID: … …, value putstatic FID:..., value …
15
JVM primer: instructions 4 Calling methods: invokevirtual N:…, param1, [param2,…] result calls Nth method of class invokespecial N calls constructors etc. invokestatic N Invokeinterface N return, ireturn, … Creating objects: new N – allocates and inits memory. Then, constructor must be called
16
JVM Primer: example int i; // An instance variable MyObj example() { MyObj o = new MyObj(); return silly(o); } MyObj silly(MyObj o) { if (o != null) { return o; } else { return o; } Method MyObj example() 0 new [Class MyObj] 3 dup 4 invokespecial [MyObj. ()] 7 astore_1 8 aload_0 9 aload_1 10 invokevirtual [silly] 13 areturn Method MyObj silly(MyObj) 0 aload_1 1 ifnull 6 4aload_1 5 areturn 6 aload_1 7 areturn
17
JVM primer: exception handling Exception handling throw N: throw an exception of class N Exception table: FROMTOClassHandler 13178
18
Part 3: Aspects implementation Munger Shadow Residue
19
AspectJ: the process Java sourceAspects source Java bytecodeAspects bytecode Java Library Aspects Library AspectJ compiler Weaver Woven program shadows mungers
20
Advice Implementation: the 4 questions WHERE- shadows WHEN- residues WHAT- the aspect code HOW- weaving
21
Join Point Shadows: WHERE Static code sections that potentially match a join point Example: “hello world” public static void main(String[] s) { System.out.println(“hello world”); } 0: getstatic [java/lang/System.out] 3: ldc [String “hello world”] 5: invokevirtual [java/io/Printstream.println] 8: return Field-get Target: from stack Args: none Method-call Target: From stack Args: From stack !Parameters must be stored and re-loaded Method-execution Target: this Args: local vars
22
Join Point Shadows: Notes Java bytecodes carry plentiful meta- information Instructions’ intent easily recognizable Shadow is completely defined by region of code No need for source code! It is sometimes impossible to determine statically if aspect should be executed residue
23
Advice compilation: WHAT Each advice compiles to a regular Java method Parameters statically typed used for matching Advice always runs in the context of aspect instance Additional information encoded in attributes Each residue compiles to a regular Java method
24
Residues: WHEN Dynamic part of the pointcut Residue types: if Computes conditions on parameters Parameters passed if necessary instanceof Checks type cflow Check the stack for cflow conditions Store cflow status in the stack Each relevant join point checks the status
25
Residues example: if residue before(): execution(void main(*)) && if(Tracing.level == 1) { System.out.println(“here”); } 0: invokestatic [A.ajc$if_0] 3: ifeq 12 6: invokestatic [A.aspectof] 9: invokevirtual [A.ajc$before$A$a6] 12: getstatic [java/lang/System.out] 15: ldc [String “hello world”] 17: invokevirtual [java/io/Printstream.println] 20: return Residue Aspect
26
Residues example: instanceof before(String s): execution(void go(*)) && args(s) { System.out.println(s); } Case 1: void go(java.lang.String) { } Advice is always called Case 2: void go(java.lang.Object) { } Advice called only if the parameter is a String
27
Residues: instanceof contd void go(java/lang/Object); 0: aload_1 1: astore_2 2: aload_2 3: instanceof[String] 6: ifeq 14# skip advice 9: invokestatic[A.aspectOf] 10: aload_1 13: invokevirtual [A.ajc$before$A$a3] 16: return Residue Aspect
28
Residues: cflow On entry to the method, compute the cflow conditions Store the result in a local variable At the join point, check the variable The test is completely dynamic Static optimization would need whole- program analysis
29
The Matching process 1. For each advice: Create a shadow munger 2. For each shadow munger: For each class: For each shadow, apply the munger [optimization] If the munger has withincode attribute, check only in that method
30
Weaving: HOW Expose the context Copy stack parameters Push local variables (for calls) Create a JoinPoint object if necessary Reflective information on the join point: getKind(), getSignature(), getLocation(), getArgs(), … Done once per shadow Insert the advice code Implementation depends on advice kind Weaving in inverse precedence order
31
Weaving: advice types Before advice Advice code just inserted in the beginning of the shadow After returning advice Call: Expose the return value Insert the code in the end of the shadow Execution: All the return points must be captured Generate gotos into a single return point
32
Weaving: more advice types After throwing advice Add a new exception handler in the enclosing method After finally advice Combine After returning and After throwing Control flow entry advice Same as before advice Control flow exit advice Same as After finally advice
33
Weaving: more advice types Around advice Replaces the original shadow code If no call to proceed, just inline the advice code If there is a call to proceed: class Closure$i extends AroundClosure { public void run() { // perform the advised code } } Create the Closure$i object and pass it as a parameter to advice Declare warning and error Just print the message, no bytecode changes
34
Weaving: inlining Advice code is [almost] never inlined Why? Because JIT does a better work. Avoids code duplication
35
Aspects performance: Benchmark Xalan – XSLT processor 826 source files, 7700 methods, 144K lines of code Measure the slowdown caused by aspects Compare to hand-coded version public aspect Trace { private static Logger log = Logger.getLogger(“xalan”); pointcut traced(): execution(* *(..)); before(): traced() { Signature s = thisJoinPointStaticPart.getSignature(); log.entering( s.getDeclaringType().getName(), s.getname()); }
36
Aspects Performance: first results Logging enabled Logging disabled
37
Aspects performance: optimizing Avoid class.getName() if not used before() traced() { if (!log.isLoggable(Level.FINER)) return; … } Check log.isLoggable in the residue pointcut traced(): execution(* *(..)) && if (log.isLoggable(Level.FINER)); Avoids method call of the aspect Store the result of log.isLoggable() pointcut traced(): … && if (enabled) && log.isLoggable() Faster than hand-coded version Remove the aspect altogether
38
Aspects performance: results Best implementation: 76% better than handcoded Same could be done manually, but impractical
39
Conclusions Weaving advices in Java is easy Rich bytecode C++ would be much harder – certainly would require source code access! More static analysis will allow for faster code
40
References Advice weaving in AspectJ, Eric Hillsdale and Jim Hugunin, In Proceedings of AOSD'04 The AspectJ project homepage, http://eclipse.org/aspectjhttp://eclipse.org/aspectj The JVM Specification book, http://java.sun.com/docs/books/vmspec/http://java.sun.com/docs/books/vmspec/
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.