No dark magic - Byte code engineering in the real world

4,182 views

Published on

ften byte code engineering is perceived as "black magic" and considered too low level. This session will not bore you with all the details of the JVM specification but provide you with a practical overview of how this byte code "swizzling" can be used in the real world instead. Several projects have sucessfully leveraged this technique to achieve some amazing things (e.g. AOP). This session will go through some of these examples and try to outline the differences between the two major libraries (BCEL and ASM). Maybe your next project can then benefit from some of this "magic".

Published in: Technology, Education
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,182
On SlideShare
0
From Embeds
0
Number of Embeds
45
Actions
Shares
0
Downloads
124
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

No dark magic - Byte code engineering in the real world

  1. 1. Torsten Curdt Java Byte Code Engineering No black magic
  2. 2. Virtual CPU Physical Machine Java Virtual Machine
  3. 3. .cstring .align 2 Native Assembler LC0: .ascii quot;Hello, world .text .align 2 .globl _main #include <stdio.h> _main: mflr r0 stmw r30,-8(r1) int main(char** args) { r0,8(r1) stw stwu r1,-80(r1) printf(quot;Hello, worldquot;); mr r30,r1 bcl 20,31,quot;L000000000 return 0; quot;L00000000001$pbquot;: } mflr r31 stw r3,104(r30) gcc -S addis r2,r31,ha16(LC0 HelloWorld.c la r3,lo16(LC0-quot;L0000 bl L_printf$LDBLStub$
  4. 4. Native Assembler #include <stdio.h> int main(char** args) mflr r0 printf(quot;Hello, worl return 0; stmw r30,-8(r1) } stw r0,8(r1) stwu r1,-80(r1) mr r30,r1 bcl 20,31,quot;L00000000001$pbquot; ... gcc -S HelloWorld.c
  5. 5. Compiled from quot;HelloW Java Assembler public class HelloWor public HelloWorld(); Code: 0: aload_0 1: invokespecial public class HelloWorld { Object.quot;<init>quot;:()V 4: return public static void main(String[] args) { public static void ma System.out.println(quot;Hello, world!quot;); Code: } 0: getstatic System.out:Ljava/io/P 3: ldc #3; / } 5: invokevirtual //Method java javap -c HelloWorld lang/String;)V 8: return
  6. 6. Java Assembler public class HelloWo public static void main(java.lang.String[]) public static void System.out.print Code: } 0: getstatic #2; //Field java/lang/ 3: ldc #3; //String Hello, world! } 5: invokevirtual #4; //Method java/io/ 8: return } javap -c HelloWorld
  7. 7. Jasmin Syntax public class HelloWo public static void .method public static main([Ljava/lang System.out.print .limit stack 2 } .limit locals 1 } .line 4 getstatic java/lang/System/out Ljava/ ldc quot;Hello, world!quot; invokevirtual java/io/PrintStream/println .line 5 return .end method
  8. 8. Tools • Disassembler: Jasper java -jar jasper.jar HelloWorld.class • Assembler: Jasmin java -jar jasmin.jar HelloWorld.j
  9. 9. Roundtrip jasmin HelloWorld.j HelloWorld.class jasper
  10. 10. Libraries • ASM (BSD-style) • BCEL (ASL) • CGLIB (ASL) • Javassist (MPL/LGPL)
  11. 11. Libraries AOP Javassist ASM CGLIB BCEL
  12. 12. BCEL • Object model based • JDK 1.4 support • Verifier • “DOM”
  13. 13. ASM • Event driven • DOM available • JDK 1.6 support • “SAX”
  14. 14. BCEL vs ASM • Community • JDK support • “DOM” vs “SAX” • API • Tool support
  15. 15. BCEL vs ASM • BCEL: xalan, findbugs, aspectj, javaflow, clirr, beanshell, just4log, ... • ASM: jardiff, javaflow, groovy, cobertura, aspectwerkz, beanshell, retroweaver, ...
  16. 16. demo
  17. 17. Generation
  18. 18. XSLTC • XSLT to java compiler • Creates a translet from xslt • Translet as JAXP transformer
  19. 19. XSLTC *.xsl SAX Parser XPath Parser XSLT Parser JAXP / TrAX API native API *.xml XSLT Compiler BCEL class
  20. 20. XSLTC Speed gregor msxml jd.xslt xsltc saxon xalan-j
  21. 21. Groovy groovy Groovy Parser source ASM ClassVisitor class
  22. 22. Analysis
  23. 23. Findbugs • Static analysis for bug patterns • False positives
  24. 24. Findbugs
  25. 25. Findbugs
  26. 26. Clirr / Jardiff • Diff for jars or class files • Detecting API changes
  27. 27. Jardiff
  28. 28. Jardiff
  29. 29. Dependency • Analyses class dependencies • Finding unused classes • Renaming classes http://vafer.org/projects/dependency
  30. 30. Dependency Set dependencies = DependencyUtils .getDependenciesOfClass( Class1.class );
  31. 31. Dependency new ResourceRenamer() { String getNewNameFor(String oldName) { if (oldName.startsWith( quot;java.util.HashMapquot;)) { return quot;my.quot; + oldName; } return oldName; }
  32. 32. Modification
  33. 33. Cobertura / Clover • Testcase coverage • Recording the execution path • Maven plugin
  34. 34. Cobertura
  35. 35. Cobertura
  36. 36. Throttling • Wrap Socket to deliver throughput according to settings • Cannot rewrite java.* classes
  37. 37. Retroweaver • Compile with jdk 1.5 features, run on 1.4 • Static conversion • Runtime conversion
  38. 38. Just4log for(int i=0; i<500000; i++) { for(int i=0; i<500000; i++) { if(log.isDebugEnabled()) { if(log.isDebugEnabled()) { log.debug(quot;messagequot; log.debug(quot;messagequot; + someLongTaskToExecute()); } + someLongTaskToExecute()); }normalCodeToExecute(); } normalCodeToExecute(); }
  39. 39. AspectJ public aspect LogAspect { declare precedence : LogAspect, *; pointcut voidCalls() : !within(LogAspect) && execution(void *.*(..)) );
  40. 40. AspectJ Object around() : voidCalls() { Signature sig = thisJoinPoint.getSignature(); log.debug('<' + getFullSig(thisJoinPoint)); Object result = proceed(); log.debug('>' + sig.getName()); return result;
  41. 41. Javaflow class MyRunnable implements Runnable { public void run() { for(int i=0; i<10; i++ ) Continuation.suspend(); }} Continuation c = Continuation.startWith( new MyRunnable()); Continuation d = Continuation.continueWith(c); ...
  42. 42. Javaflow
  43. 43. What you can do • reflection without j.l.reflection • generate classes on the fly • implement interface on the fly
  44. 44. What you can do • change visibility • extend classes that are final • modify vs forking • ...
  45. 45. Thanks!

×