Presentation is loading. Please wait.

Presentation is loading. Please wait.

Advice Weaving in AspectJ Paper by Erik Hilsdale Jim Hugunin Presented by Shay Cohen.

Similar presentations


Presentation on theme: "Advice Weaving in AspectJ Paper by Erik Hilsdale Jim Hugunin Presented by Shay Cohen."— Presentation transcript:

1 Advice Weaving in AspectJ Paper by Erik Hilsdale Jim Hugunin Presented by Shay Cohen

2 Introduction Implementation of advice weaving in AspectJ – ver 1.1 The Compilation Process Join Points Shadows Matching Weaving Compile time performance Performance of woven code

3 The Compilation Process – Source File Compilation Each advice declaration is compiled into a standard Java method before(String s): execution(void go(*)) && args(s) { System.out.println(s); } Is compiled into a method encapsulating the body of the advice public void ajc$before$A$a9(); 0: getstatic [java/lang/System.out] 3: aload_1 4: invokevirtual [java/io/PrintStream.println] 7: return

4 Source File Compilation – cont. Reflection is made by three special variables added to the advice declaration. (…, JoinPoint thisJoinPoint, JoinPoint.StaticPart thisJoinPointStaticPart, JoinPoint.StaticPart thisEncolsingJoinPointStaticPart) Optimization - variables which are not referred to within the body of the advice are removed from the signature Optimization - determine if all uses of thisJoinPoint can be replaced with thisJoinPointStaticPart.

5 Source File Compilation – cont. Around advice in AspectJ uses the special form proceed Generating a method which takes in all of the original arguments to the around method plus an additional AroundClosure object The body of the proceed method will call a method on the AroundClosure

6 Source File Compilation – cont. /* ******************************************************************* * Copyright (c) Xerox Corporation, * 2002 Palo Alto Research Center, Incorporated (PARC). * All rights reserved. * This program and the accompanying materials are made available * under the terms of the Common Public License v1.0 * which accompanies this distribution and is available at * * * Contributors: * Xerox/PARC initial implementation * ******************************************************************/ package org.aspectj.runtime.internal; public abstract class AroundClosure { //private Object[] state; public AroundClosure(/* Object[] state */) { // this.state = state; } protected Object[] state; protected Object[] preInitializationState; public AroundClosure(Object[] state) { this.state = state; } public Object[] getPreInitializationState() { return preInitializationState; } /** * This takes in the same arguments as are passed to the proceed * call in the around advice (with primitives coerced to Object types) */ public abstract Object run(Object[] args) throws Throwable; }

7 The Compilation Process – Bytecode transformation “static shadow” - certain principled places in bytecode represent possible join points The weaver must instrument the bytecode to insert calls to the an advice whenever a condition is met. For each such static shadow, it checks each piece of advice in the system and determines if the advice's pointcut could match that static shadow.

8 Bytecode transformation - cont. void go(java/lang/String): 0: return void go(java/lang/String): 0: invokestatic [A.aspectOf] 3: invokevirtual [A.ajc$before$A$a3] 6: return Transformed

9 Bytecode transformation - cont. void go(java/lang/Object): 0: return void go(java/lang/Object): 0: aload_1 # copy first argument into 1: astore_2 # a temporary frame location 2: aload_2 # check whether argument 3: instanceof [String] # is actually a String 6: ifeq 19 # if not, skip advice 9: invokestatic [A.aspectOf] # get aspect 12: aload_2 # load argument again 13: checkcast [String] # guaranteed to succeed 16: invokevirtual [A.ajc$before$A$a3] # run advice 19: return Transformed before(String s): execution(void go(*)) && args(s) { System.out.println(s); }

10 Bytecode transformation - cont. Instanceof – If objectref is not null and is an instance of the resolved class or array or implements the resolved interface, the instanceof instruction pushes an int result of 1 as an int on the operand stack. Otherwise it pushes an int result of 0. The Java Virtual Machine Specification, Second Edition Tim Lindholm, Franck Yellin

11 Bytecode transformation - cont. public aspect WeavingAspect { before (String s): execution(void go(*)) && args(s) { System.out.println("before (String s): execution(void go(*)) && args(s) " + s); } before (Object s): execution(void go(*)) && args(s) { System.out.println("before (Object s): execution(void go(*)) && args(s) " + s); }

12 public class WeavingObject { public static void main(String[] args) { WeavingObject obj = new WeavingObject(); String s = null; obj.go(s); System.out.println(); s = new String("String"); obj.go(s); } public void go(Object s) { System.out.println("go(Object s) " + s); } before (Object s): execution(void go(*)) && args(s) null go(Object s) null before (String s): execution(void go(*)) && args(s) String before (Object s): execution(void go(*)) && args(s) String go(Object s) String Bytecode transformation - cont.

13 Join point shadows – What defines a join point shadow A join point is a point in the dynamic call graph of a running program where the behavior of the program can be modified by advice. Every dynamic join point has a corresponding static shadow in the source code or bytecode of the program. a shadow represents a region of bytecode associated with a join point

14 What defines a join point shadow - cont. kind signaturethis targetargsBytecode shadow Method-execution methodALOAD_0 or noneSame as thisLocal varsEntire code segment of method Method-call methodALOAD_0 or noneFrom stack From stackInvokeinterface, invokespecial (only for privates), invokestatic, invokevirtual Constructor-exec constructorALOAD_0Same as thisLocal varsCode segment of after call to super Constructor-call constructorALOAD_0 or noneNoneFrom stackInvokespecial (plus some extra pieces) Field-get FieldALOAD_0 or noneFrom stacknoneGetfield or getstatic Field-set FieldALOAD_0 or noneFrom stackFrom stackPutfield or putstatic Advice-execution NoneALOAD_0Same as thisLocal varsCode segment of corresponding method Initialization Corresp.ALOAD_0Same as thisComplexRequires inlining of all constructors in a given class constructor into one Static-initialization TypenameNoneNoneNoneCode segment of Pre-initialization Corresp. NoneNoneLocal varsCode segment of before call to super, constructor this may require in-lining Exception-handler Typename ALOAD_0 or noneNoneFrom stackStart is found from exception handler table. execution of exception (only before advice allowed because end is poorly defined in bytecode)

15 The shadows of “hello world”, Method call 0: getstatic [java/lang/System.out] 3: ldc [String hello world] 5: invokevirtual [java/io/PrintStream.println] 8: return 0: getstatic [java/lang/System.out] 3: ldc [String hello world] 5: invokestatic [A.aspectOf] 8: invokevirtual [A.ajc$before$A$15a] 11: invokevirtual [java/io/PrintStream.println] 14: return Transformed

16 The shadows of “hello world”, Exposing method call - cont. 0: getstatic [java/lang/System.out] 3: ldc [String hello world] 5: invokevirtual [java/io/PrintStream.println] 8: return 0: getstatic [java/lang/System.out] 3: ldc [String hello world] 5: astore_1 6: astore_2 7: invokestatic [A.aspectOf] 10: aload_2 11: invokevirtual [A.ajc$before$A$15a] 14: aload_2 15: aload_1 16: invokevirtual [java/io/PrintStream.println] 19: return Transformed

17 Matching – Residues Advice and other advice-like entities are represented by shadow munger objects, each of which contains a pointcut designator (PCD) When the PCDs depend on the dynamic state at the join point this mismatch is resolved by adding a dynamic test that captures the dynamic part of the matching. This dynamic test is the residue of the match.

18 Residues – cont. 0: getstatic [java/lang/System.out] 3: ldc [String hello world] 5: invokevirtual [java/io/PrintStream.println] 8: return 0: invokestatic [A.ajc$if_0] # dynamic test 3: ifeq 12 6: invokestatic [A.aspectOf] 9: invokevirtual [Method A.ajc$before$A$a6] 12: getstatic [java/lang/System.out] 15: ldc ["hello world"] 17: invokevirtual java/io/PrintStream.println] 20: return Transformed before(): execution(void main(*)) && if(Tracing.level == 1) { System.out.println("got here"); }

19 Residues, Cflow – cont. In AspectJ-1.1 this matching is implemented entirely as a dynamic test on the join point. The current implementation of cflow uses a thread-local stack.

20 Fastmatch A “regular” Match is done by if a shadow munger is defined for each of the static shadow. Matching every join point shadow in every class file can be a time consuming process In fastmatch, every shadow munger is matched to the constant pool information in each class file.

21 Synthetic methods and matching Compilers for the Java language generate methods and fields that are not in the original source code Fortunately, they can be generally recognized by the SYNTHETIC attribute in the Java bytecode There are many additional synthetic methods added by the AspectJ compiler - AJ_SYNTHETIC

22 Weaving - Context exposure collect up the desired state from each matching munger modify code so desired state is in temporaries astore_3 # arg2 astore_4 # arg1 astore_5 # target aload_5 # repush aload_4 # repush aload_3 # repush mungers need target, arg1, and arg2

23 Shadow Munger Implementation Each shadow munger transforms the shadow by adding code inside the boundary of the shadow. apply mungers to shadow in inverse precedence order before after throwing before

24 before advice insert code at beginning of shadow code pushes aspect, then arguments to advice, then invokes the advice method guard the inserted code with residual test, if necessary aload_5 # target instanceof [Foo] ifeq end: invokestatic [A.aspectOf] [push args to advice] invokevirtual [A.before379] end: before with residual target(Foo) weaving

25 after returning advice first, process shadow to ensure exactly one exit point: replace all return (or ireturn, freturn, etc) bytecodes with goto shadow’s end add single return (or ireturn, freturn, etc) at end of shadow if there was one inside shadow return goto weaving

26 after returning advice – cont. then add residual and advice code to end of shadow return goto advice weaving

27 Factorial class Factorial { static int fact(int n) { if (n == 0) return 1; else return n * fact(n-1); } public static void main(String[] args) { System.out.println(fact(3)); }

28 after returning advice – cont. static int fact(int); 0: iload_0 1: ifne 6 4: iconst_1 5: ireturn 6: iload_0 7: iconst_1 8: isub 9: invokestatic [fact] 12: iload_0 13: imul 14: ireturn static int fact(int); 0: iload_0 1: ifne 8 4: iconst_1 5: goto 19 8: iload_0 9: iconst_1 10: isub 11: invokestatic [fact] 14: iload_0 15: imul 16: goto 19 19: dup 20: istore_1 21: invokestatic [A.aspectOf] 24: iload_1 25: invokevirtual [A.ajc$afterReturning$A$ff] 28: ireturn after() returning(int i): execution(int fact(int))

29 around advice first, extract code from shadow into its own method in containing class replace shadow code with call to new method invokevirtual or invokestatic weaving

30 around advice – cont. create new class, whose run method is just a call to extracted method invokevirtual or invokestatic run Closure837 weaving

31 Why we don’t inline advice code The primary performance overhead of AspectJ code is caused by the aspect-instance lookup and method call Inlining can be done much more effectively by a JIT need to either increase the visibility of the accessed members, which would let anyone see them Inlining is used in default around advice and privileged aspects

32 Compile time performance time required to compile the xalan xslt processor from apache.org

33 Compile time performance – cont. Improvements can be achieved by: Basic engineering work. improving the fastmatch algorithm to handle more cases support incremental recompilation

34 Performance of woven code we measured the compilation time of a single large tool, the Xalan XSLT processor from apache.org (paper talks about compile-time performance) for performance evaluation we used the XSLTMark benchmark we chose to benchmark logging as it is the most invasive of the common AspectJ applications with logging enabled, both AspectJ and a hand-rolled logger had a 60,000% overhead all following measurements are with logging disabled benchmarks

35 Performance of woven code - hand-rolled logging to get a baseline we produced a hand- rolled implementation of a logging policy add a log to each of the 826 classes static Logger log = Logger.getLogger(“xalan”); add a call to each of the 7711 methods log.entering(“ ”, “ ”) benchmarks

36 Performance of woven code - an unfortunate surprise Logging enabled L benchmarks 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()); }

37 Performance of woven code - an unfortunate surprise Logging disabled 2900% overhead (!) benchmarks 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()); } Use Signature.getDeclaringClassName()

38 Performance of woven code - guarding with isLoggable() 22% over hand- coded benchmarks public aspect Trace { private static Logger log = Logger.getLogger(“xalan”); pointcut traced(): execution(* *(..)); before(): traced() { if (!log.isLoggable(Level.FINER)) return; Signature s = thisJoinPointStaticPart.getSignature(); log.entering( s.getDeclaringType().getName(), s.getname()); }

39 Performance of woven code - using the if pointcut 8% over hand- coded benchmarks public aspect Trace { private static Logger log = Logger.getLogger(“xalan”); pointcut traced(): execution(* *(..)) && if (log.isLoggable(Level.FINER)); before(): traced() { Signature s = thisJoinPointStaticPart.getSignature(); log.entering( s.getDeclaringType().getName(), s.getname()); }

40 Performance of woven code - using a field 8% under hand-coded cross-cutting optimization benchmarks public aspect Trace { private static Logger log = Logger.getLogger(“xalan”); static boolean enabled; pointcut traced(): execution(* *(..)) && if(enabled) && if(log.isLoggable(Level.FINER)); before(): traced() { Signature s = thisJoinPointStaticPart.getSignature(); log.entering( s.getDeclaringType().getName(), s.getname()); }

41 (a late addition)

42 Conclusions Complier Implementation is a major issue in performance The complier performance has an impact on aspects users community Aspects code writing is a major issue in performance AspectJ is getting faster by the minute

43 The end


Download ppt "Advice Weaving in AspectJ Paper by Erik Hilsdale Jim Hugunin Presented by Shay Cohen."

Similar presentations


Ads by Google