Transcript
  • 1. Programmer's Survival Kit:Code Injection for Troubleshooting Jakub Hol, Iterate AS http://bit.ly/codeinject

2. Learn code injection it can save your day! 3. The power of code injection Code injectionaspect-oriented programming (AOP*):

  • Modify existingbinaryclasses at build/load time

4. Inject the same code into one or multiple places (DRY) 5. Lifecycle: Write aspect > weave > run (For AOP check Wikipedia or Spring docs.) * I will use AOP and Code Injection interchangeably, however inaccurate that is 6. 3 tools, 2 (3) examples 7. 1. The omnipresent Java Proxy

  • In JRE java.lang.reflect.*

8. Not true AOP, applied manually 9. Can only proxy interfaces 10. Verbose 11. Client JDBC code: PreparedStatement rawStmt = c.prepareStatement( "INSERT ..." ); PreparedStatement loggingStmt =(PreparedStatement) Proxy.newProxyInstance(...,newBatchLogger(rawStmt)); for( inti = 0; i < data. length ; i++) { loggingStmt.setString(1, data[i]); loggingStmt.addBatch(); // end a row, start a new one if(isMultipleOfBatchSize(i)) loggingStmt.executeBatch(); // Logs st. on failure } Ex.: Log data of a failed batch (0) 12. classBatchLoggerimplements InvocationHandler{ publicObjectinvoke (Object proxy , Method method , Object[] args)throwsThrowable { try{ return method.invoke ( this . target , args);}catch(BatchUpdateException e) { } } ... Ex.: Log data of a failed batch (1) 13. classBatchLoggerimplements InvocationHandler{ publicObjectinvoke (Object proxy , Method method , Object[] args)throwsThrowable { if(isSetSomething(method)) { /* rememberargs =column */ } if(isAddBatch(method)) { /*adda new row */ } try{ return method.invoke ( this . target , args);}catch(BatchUpdateException e) { /*logrememberedrows in the batch*/ throwe; } finally{ if(isExecuteBatch(method)) { /*reset rememberedrows */ } } } ... Ex.: Log data of a failed batch (2) 14.

  • No run-time dependencies

15. Build-time weaving 16. Somehow low-level 17. Limited power 18. Weaving manually / custom Ant task For an example, see the accompanying source code project and blog post. For an alternative w/o most cons see GluonJ. 2. The independent Javassist 19. 3. The almighty AspectJ

  • Full-fledged AOP

20. Build-time/load-time weaving 21. Weaving with Ant or Java agentlib 22. Depends on AspectJ libraries at the run-time 23. @Aspect public classLoggingAspect { @Around ( "execution(private void TooQuiet3rdPartyClass.failingMethod(Object))" ) publicObject interceptAndLog(ProceedingJoinPoint invocation)throwsThrowable { try{ returninvocation.proceed(); }catch(Exception e) { thrownew RuntimeException( "Failed for: "+ invocation.getArgs()[0] , e); } } } Ex.: Include argument in exception 24. What it can do

  • Troubleshooting: Improved logging, ...

25. Cross-cutting concerns: Security, transactions, traits, ... - see EJBs 26. Testing:code coverage, mutation testing, ... 27. Code injection/AOP is great but don'toveruse it see Glassbox.sf.net 28. Thank you!

  • Much more detailed explanation with more topics and a link to full source codes:

29. http://bit.ly/codeinject 30. feedback via the blog post's comments welcomed! 31. Bonus slides 32. // Advice my.example.TargetClass.myMethod(..) with a before and afteradvices finalClassPool pool = ClassPool. getDefault (); finalCtClass compiledClass = pool.get( "my.example.TargetClass" ); finalCtMethod method =compiledClass .getDeclaredMethod( "myMethod" ); method.addLocalVariable( "startMs" , CtClass. longType ); method.insertBefore( "startMs = System.currentTimeMillis();" ); method.insertAfter( "{final long endMs = System.currentTimeMillis(); System.out.println("Executed in ms: " + (endMs-startMs));}" ); compiledClass.writeFile( "/tmp/javassist/modifiedClassesFolder" ); // Enjoy the new / tmp /javassist/my/example/TargetClass.class Ex: Performance monitoring withJavassist