0
Mastering Java Bytecode with ASMLearn some bytecode to yourself!
whoamiAnton ArhipovJava Dev / Product LeadZeroTurnaround, JRebelMessing with bytecode since 2010anton@zeroturnaround.com@a...
whoamiAnton ArhipovJava Dev / Product LeadZeroTurnaround, JRebelMessing with bytecode since 2010anton@zeroturnaround.com@a...
Why Bytecode?•   Know your platform!•   Build your own JVM language?•   Programming models (AOP, ORM)•   Awesome tools (li...
Bytecode 101     Instrumentation API       javap   ObjectWeb ASM
Bytecode 101  Gentle introduction
Adding Two ValuesA+B
Adding Two ValuesA+BAB+
Adding Two ValuesA+BAB+
Adding Two ValuesA+B   PUSH A                      AAB+
Adding Two ValuesA+B   PUSH 1      PUSH 2                      BAB+                   A
Adding Two ValuesA+B   PUSH 1      PUSH 2                      15AB+   ADD
Adding Two ValuesA+B   ICONST_1      ICONST_2                      15AB+   IADD
TYPE     OPERATION• <TYPE> ::= b, s, c, i, l, f, d, a• constant values (ldc, iconst_1)•   Local variables and stack intera...
Model ofExecution
Enter JVMJVM process
Enter ThreadsThread A    Thread B   Thread C   Thread D
Enter Frames
The FrameLocal variables0 1 2        …    NOperand stack                  #1                        Constant              ...
Juggling The Stack
Juggling The Stackdup                      Apop                      Bswapdup_x1dup2_x1
Juggling The Stackdup                      Apop                      Aswap                     Bdup_x1dup2_x1
Juggling The Stackdup                      Apop                      Bswapdup_x1dup2_x1
Juggling The Stackdup                      Bpop                      Aswapdup_x1dup2_x1
Juggling The Stackdup                      Bpop                      Aswap                     Bdup_x1dup2_x1
Juggling The Stackdup                      Bpop                      Aswap                     Bdup_x1                   B...
Local Variables
Local Variables                         Stackvar      value                      depth     value0                      ldc...
Local Variables                         Stackvar      value                      depth     value0                      ldc...
Local Variables                         Stackvar      value                      depth     value0                      ldc...
Local Variables                         Stackvar      value                      depth     value0                      ldc...
Local Variables                         Stackvar      value                      depth     value0                      ldc...
Local Variables                         Stackvar      value                      depth     value0                      ldc...
load  LocalVariables           Stack  Table            store
Method Invoсation
Method Invocationobj.method(param1, param2);
Method Invocationobj.method(param1, param2);      push obj      push param1      push param2      invoke method
Method Invocationobj.method(param1, param2);                              obj      push obj      push param1      push par...
Method Invocationobj.method(param1, param2);                              param1      push obj                 obj      pu...
Method Invocationobj.method(param1, param2);                              param2      push obj                param1      ...
Method Invocationobj.method(param1, param2);                              obj?      push obj      push param1      push pa...
Operator Overloading
Operator Overloading[int] A + B    [Foo] A.plus(B)
Operator Overloading[int] A + B    [Foo] A.plus(B)     push A       push A     push B       push B     iadd         invoke...
Operator Overloading[int] A + B    [Foo] A + B     push A       push A     push B       push B     iadd         invokevirt...
pop   push Stack
pop   push            load LocalVariables            Stack  Table            store
pop   push            load LocalVariables            Stack  Table            store
pop      push            load LocalVariables                       Stack             invoke  Table            store       ...
javapThe disassembler
javap• Java class file disassembler• Used with no options shows class structure only   – Methods, superclass, interfaces, ...
C:workgeeconclasses>javap Hello -c
C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello();  C...
C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello();  C...
C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello();  C...
C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello();  C...
C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello();  C...
C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello();  C...
C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello();  C...
C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello();  C...
C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello();  C...
C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello();  C...
What’s #1,#2, etc ?C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object...
SLIDESGOTO: IDESLIDESIDE: JAVAP DEMO
ASMThe de facto standard for bytecode manipulation
ASM• “All purpose bytecode manipulation  and analysis framework”• De facto standard bytecode library• http://asm.ow2.org
Basic Process• Construct ClassWriter• Stack up the visitors for:  • annotations, methods, fields, etc• Write out bytes
Hello.java
ClassWriterClassWriter cw = new ClassWriter(     ClassWriter.COMPUTE_MAXS |     ClassWriter.COMPUTE_FRAMES);
COMPUTE_***• COMPUTE_MAXS –ASM will calculate max stack/local vars• COMPUTE_FRAMES –ASM will calculate Java 6 stack map
Visit Classcv.visit(V1_6,    ACC_PUBLIC,    "X",    null,    "java/lang/Object",    null);
Opcodes• Interface full of constants  –Bytecodes  –Visibility modifiers  –Java versions  –Other stuff
ACC_***• Some you know  –ACC_PUBLIC, ACC_ABSTRACT, etc• Some you (probably) don’t  –ACC_BRIDGE, ACC_SYNTHETIC
Class Names      "java/lang/Object"packageClass.replaceAll(., /)
Type Descriptors
Type Descriptors  B      byte  C      char  S      string  I      int  J      long  F      float  D      double  Z      bo...
Type DescriptorsLsome/Class;
Type Descriptors[Lsome/Class;
Method Signatures()V                      void foo()(Ljava/lang/Object;)I    int foo(Object)([Ljava/lang/String;)V   void ...
Visit MethodMethodVisitor constructor =  cv.visitMethod(ACC_PUBLIC,  "<init>",  "()V",  null,  null);MethodVisitor mv = cv...
Visit MethodMethodVisitor constructor =  cv.visitMethod(ACC_PUBLIC,  "<init>",            Wat!? o_O  "()V",  null,  null);...
Special Methods• <init>  –Constructor• <clinit>  –Static initializer
MethodVisitor• Visit annotations• Visit code  – Bytecodes, local variables, line numbers, etc• Visit maxs  – Pass bogus va...
Constructorc.visitVarInsn(ALOAD, 0);c.visitMethodInsn(INVOKESPECIAL,   "java/lang/Object", "<init>", "()V");c.visitInsn(RE...
Constructorc.visitVarInsn(ALOAD, 0);c.visitMethodInsn(INVOKESPECIAL,   "java/lang/Object", "<init>", "()V");c.visitInsn(RE...
public static void main()
public static void main()mv.visitFieldInsn(GETSTATIC,      "java/lang/System", "out",      "Ljava/io/PrintStream;");mv.vis...
public static void main()mv.visitFieldInsn(GETSTATIC,      "java/lang/System", "out",                                     ...
Enter Loops
Enter Loopsstart:  int i = 0loop:  print "Hello"  i=i+1  if i < 10 goto loopend: return
Enter Loopsstart:  int i = 0         GOTO isn’t harmful ;)loop:  print "Hello"  i=i+1  if i < 10 goto loopend: return
Enter Loops0:    iconst_01:    istore_12:    iload_13:    bipush    105:    if_icmpge 22System.out.println(“Hello”)16: iin...
Enter Loopsstart: iconst_0  1: istore_1loop: iload_1  3: bipush     10  5: if_icmpge end System.out.println(“Hello”) 16: i...
Enter Loopsstart: iconst_0  1: istore_1           int i = 0loop: iload_1  3: bipush     10  5: if_icmpge end System.out.pr...
Enter Loopsstart: iconst_0  1: istore_1loop: iload_1  3: bipush     10      i < 10  5: if_icmpge end System.out.println(“H...
Enter Loopsstart: iconst_0  1: istore_1loop: iload_1  3: bipush     10  5: if_icmpge end System.out.println(“Hello”) 16: i...
Enter Loopsstart: iconst_0  1: istore_1loop: iload_1  3: bipush     10  5: if_icmpge end System.out.println(“Hello”) 16: i...
Enter ASM LoopsLabel start = new Label();Label loop = new Label();Label end = new Label();// i = 0mv.visitLabel(start);mv....
Enter ASM LoopsLabel start = new Label();Label loop = new Label();Label end = new Label();// i = 0mv.visitLabel(start);mv....
Enter ASM LoopsLabel start = new Label();Label loop = new Label();Label end = new Label();       //increment & continue th...
ClassWriter
geecon$ java HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello
ASMified     ASMifierClassVisitormv = cw.visitMethod(ACC_PUBLIC, "getId", "(I)I", null, null);mv.visitCode();Label l0 = ne...
Bytecodeinstrumentation Some magic for your own good
WAT!?Ninja.class           Ninja.class’10101010101           1010101010111000101010           1110000101010101010001      ...
Who?          Containers (Java EE, Spring)                   TerracottaJRebel                         Tapestry         Byt...
How?• Add –javaagent to hook into class loading  process• Implement ClassFileTransformer• Use bytecode manipulation librar...
How ? (2)• Use custom ClassLoader  – Override ClassLoader#findClass  – Use ClassReader(String) to read the class    in and...
java.lang.instrumentimport java.lang.instrument.ClassFileTransformer;import java.lang.instrument.Instrumentation;public cl...
java.lang.instrumentimport java.lang.instrument.ClassFileTransformer;import java.lang.instrument.Instrumentation;public cl...
java.lang.instrumentimport java.lang.instrument.ClassFileTransformer;import java.lang.instrument.Instrumentation;public cl...
j.l.instrument.ClassFileTransformernew ClassFileTransformer() {  public byte[] transform(ClassLoader loader, String classN...
j.l.instrument.ClassFileTransformernew ClassFileTransformer() {  public byte[] transform(ClassLoader loader, String classN...
j.l.instrument.ClassFileTransformernew ClassFileTransformer() {  public byte[] transform(ClassLoader loader, String classN...
public class MyClassLoader extends ClassLoader { protected Class findClass(String name)                          throws Cl...
SLIDESGOTO: IDESLIDESIDE: ASM DEMO
@antonarhipov    anton@zeroturnaround.comhttps://github.com/antonarhipov/asmdemo
Mastering java bytecode with ASM - GeeCON 2012
Mastering java bytecode with ASM - GeeCON 2012
Upcoming SlideShare
Loading in...5
×

Mastering java bytecode with ASM - GeeCON 2012

3,645

Published on

Published in: Technology, Education
1 Comment
29 Likes
Statistics
Notes
No Downloads
Views
Total Views
3,645
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
189
Comments
1
Likes
29
Embeds 0
No embeds

No notes for slide
  • Why would learn Java bytecode and ASM at all?Well, creating a brand new JVM language might be a good idea  This is what all the cool kids are doing, right?Secondly – programming model that is exposed by many frameworks is backed with bytecode generation or instrumentation. AspectJ, for instance uses bytecode instrumentation extensively.Also, there are some many awesome tools that do awesome stuff, like …. JRebel for instance 
  • This presentation provides some pointers to the subject
  • Actually, before going further, let’s mention javap– the Java class disassembler. The output of javap command isn’t particularly useful as there’s no way to modify it and compile back to the executable code. However, it is much more easier to read the bytecodes produced by javap, rather than the code that is written using ASM API. So, javap is good for reference when studying the bytecode.
  • The most common scenario to generate bytecode that corresponds to the example source, is to create ClassWriter, visit the structure – fields, methods, etc, and after the job is done, write out the final bytes.
  • Let’s go on and construct a ClassWriter.. The constructor takes anint which is composed of different flags.COMPUTE_MAXS says that the sizes of local variables and operand stack parts will be computed automatically. Still have to call visitMaxs with any argumentsCOMPUTE_FRAMES – everything is computed automatically. ASM will compute the stack map, still have to call visitMaxs
  • ... using ASMifierClassVisitor (ASMifier in ASM4). The output is rather noisy, with all the labels,but the noise is easy to remove.
  • Transcript of "Mastering java bytecode with ASM - GeeCON 2012"

    1. 1. Mastering Java Bytecode with ASMLearn some bytecode to yourself!
    2. 2. whoamiAnton ArhipovJava Dev / Product LeadZeroTurnaround, JRebelMessing with bytecode since 2010anton@zeroturnaround.com@antonarhipov @javarebel
    3. 3. whoamiAnton ArhipovJava Dev / Product LeadZeroTurnaround, JRebelMessing with bytecode since 2010anton@zeroturnaround.com@antonarhipov @javarebel
    4. 4. Why Bytecode?• Know your platform!• Build your own JVM language?• Programming models (AOP, ORM)• Awesome tools (like JRebel )... just bored?
    5. 5. Bytecode 101 Instrumentation API javap ObjectWeb ASM
    6. 6. Bytecode 101 Gentle introduction
    7. 7. Adding Two ValuesA+B
    8. 8. Adding Two ValuesA+BAB+
    9. 9. Adding Two ValuesA+BAB+
    10. 10. Adding Two ValuesA+B PUSH A AAB+
    11. 11. Adding Two ValuesA+B PUSH 1 PUSH 2 BAB+ A
    12. 12. Adding Two ValuesA+B PUSH 1 PUSH 2 15AB+ ADD
    13. 13. Adding Two ValuesA+B ICONST_1 ICONST_2 15AB+ IADD
    14. 14. TYPE OPERATION• <TYPE> ::= b, s, c, i, l, f, d, a• constant values (ldc, iconst_1)• Local variables and stack interaction (load/store)• Array operations (aload, astore)• Math (add, sub, mul, div)• Boolean/bitwise operations (iand, ixor)• Comparisons & branching (cmpl, ifeq, jsr, tableswitch)• Conversions (l2d, i2l)
    15. 15. Model ofExecution
    16. 16. Enter JVMJVM process
    17. 17. Enter ThreadsThread A Thread B Thread C Thread D
    18. 18. Enter Frames
    19. 19. The FrameLocal variables0 1 2 … NOperand stack #1 Constant Pool
    20. 20. Juggling The Stack
    21. 21. Juggling The Stackdup Apop Bswapdup_x1dup2_x1
    22. 22. Juggling The Stackdup Apop Aswap Bdup_x1dup2_x1
    23. 23. Juggling The Stackdup Apop Bswapdup_x1dup2_x1
    24. 24. Juggling The Stackdup Bpop Aswapdup_x1dup2_x1
    25. 25. Juggling The Stackdup Bpop Aswap Bdup_x1dup2_x1
    26. 26. Juggling The Stackdup Bpop Aswap Bdup_x1 Bdup2_x1 A
    27. 27. Local Variables
    28. 28. Local Variables Stackvar value depth value0 ldc "Hello" 0 astore_01 1 iconst_12 astore_1 23 aload_0 34 4
    29. 29. Local Variables Stackvar value depth value0 ldc "Hello" 0 "Hello" astore_01 1 iconst_12 astore_1 23 aload_0 34 4
    30. 30. Local Variables Stackvar value depth value0 ldc "Hello" 0 "Hello" astore_01 1 iconst_12 astore_1 23 aload_0 34 4
    31. 31. Local Variables Stackvar value depth value0 ldc "Hello" 0 "Hello" 1 astore_01 1 iconst_12 astore_1 23 aload_0 34 4
    32. 32. Local Variables Stackvar value depth value0 ldc "Hello" 0 "Hello" astore_01 1 1 iconst_12 astore_1 23 aload_0 34 4
    33. 33. Local Variables Stackvar value depth value0 ldc "Hello" 0 "Hello" "Hello" astore_01 1 1 iconst_12 astore_1 23 aload_0 34 4
    34. 34. load LocalVariables Stack Table store
    35. 35. Method Invoсation
    36. 36. Method Invocationobj.method(param1, param2);
    37. 37. Method Invocationobj.method(param1, param2); push obj push param1 push param2 invoke method
    38. 38. Method Invocationobj.method(param1, param2); obj push obj push param1 push param2 invoke method
    39. 39. Method Invocationobj.method(param1, param2); param1 push obj obj push param1 push param2 invoke method
    40. 40. Method Invocationobj.method(param1, param2); param2 push obj param1 push param1 obj push param2 invoke method
    41. 41. Method Invocationobj.method(param1, param2); obj? push obj push param1 push param2 invoke method
    42. 42. Operator Overloading
    43. 43. Operator Overloading[int] A + B [Foo] A.plus(B)
    44. 44. Operator Overloading[int] A + B [Foo] A.plus(B) push A push A push B push B iadd invokevirtual plus
    45. 45. Operator Overloading[int] A + B [Foo] A + B push A push A push B push B iadd invokevirtual plus
    46. 46. pop push Stack
    47. 47. pop push load LocalVariables Stack Table store
    48. 48. pop push load LocalVariables Stack Table store
    49. 49. pop push load LocalVariables Stack invoke Table store pop push load Local Variables Stack Table store
    50. 50. javapThe disassembler
    51. 51. javap• Java class file disassembler• Used with no options shows class structure only – Methods, superclass, interfaces, etc• -c shows the bytecode• -private shows all methods and members• -s prints internal signatures• -l prints line numbers and local variable tables• -verbose for verbosity 
    52. 52. C:workgeeconclasses>javap Hello -c
    53. 53. C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: the default constructor 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
    54. 54. C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: push this to stack 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
    55. 55. C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return invoke <init> on this
    56. 56. C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V super() 4: return
    57. 57. C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
    58. 58. C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: returnpublic static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello, World! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
    59. 59. C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return get static fieldpublic static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello, World! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
    60. 60. C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: returnpublic static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello, World! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V load string to the stack
    61. 61. C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: returnpublic static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello, World! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V invoke method with parameter
    62. 62. C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: returnpublic static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello, World! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
    63. 63. What’s #1,#2, etc ?C:workgeeconclasses>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: returnpublic static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello, World! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
    64. 64. SLIDESGOTO: IDESLIDESIDE: JAVAP DEMO
    65. 65. ASMThe de facto standard for bytecode manipulation
    66. 66. ASM• “All purpose bytecode manipulation and analysis framework”• De facto standard bytecode library• http://asm.ow2.org
    67. 67. Basic Process• Construct ClassWriter• Stack up the visitors for: • annotations, methods, fields, etc• Write out bytes
    68. 68. Hello.java
    69. 69. ClassWriterClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
    70. 70. COMPUTE_***• COMPUTE_MAXS –ASM will calculate max stack/local vars• COMPUTE_FRAMES –ASM will calculate Java 6 stack map
    71. 71. Visit Classcv.visit(V1_6, ACC_PUBLIC, "X", null, "java/lang/Object", null);
    72. 72. Opcodes• Interface full of constants –Bytecodes –Visibility modifiers –Java versions –Other stuff
    73. 73. ACC_***• Some you know –ACC_PUBLIC, ACC_ABSTRACT, etc• Some you (probably) don’t –ACC_BRIDGE, ACC_SYNTHETIC
    74. 74. Class Names "java/lang/Object"packageClass.replaceAll(., /)
    75. 75. Type Descriptors
    76. 76. Type Descriptors B byte C char S string I int J long F float D double Z boolean V void
    77. 77. Type DescriptorsLsome/Class;
    78. 78. Type Descriptors[Lsome/Class;
    79. 79. Method Signatures()V void foo()(Ljava/lang/Object;)I int foo(Object)([Ljava/lang/String;)V void main(String[])
    80. 80. Visit MethodMethodVisitor constructor = cv.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);MethodVisitor mv = cv.visitMethod( ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
    81. 81. Visit MethodMethodVisitor constructor = cv.visitMethod(ACC_PUBLIC, "<init>", Wat!? o_O "()V", null, null);MethodVisitor mv = cv.visitMethod( ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
    82. 82. Special Methods• <init> –Constructor• <clinit> –Static initializer
    83. 83. MethodVisitor• Visit annotations• Visit code – Bytecodes, local variables, line numbers, etc• Visit maxs – Pass bogus values if COMPUTE_MAX
    84. 84. Constructorc.visitVarInsn(ALOAD, 0);c.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");c.visitInsn(RETURN);c.visitMaxs(0, 0);
    85. 85. Constructorc.visitVarInsn(ALOAD, 0);c.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");c.visitInsn(RETURN);c.visitMaxs(0, 0); aload_0 invokespecial return
    86. 86. public static void main()
    87. 87. public static void main()mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");mv.visitLdcInsn("Hello");mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");mv.visitInsn(RETURN);
    88. 88. public static void main()mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", getstatic "Ljava/io/PrintStream;"); ldc “Hello” invokevirtualmv.visitLdcInsn("Hello"); returnmv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");mv.visitInsn(RETURN);
    89. 89. Enter Loops
    90. 90. Enter Loopsstart: int i = 0loop: print "Hello" i=i+1 if i < 10 goto loopend: return
    91. 91. Enter Loopsstart: int i = 0 GOTO isn’t harmful ;)loop: print "Hello" i=i+1 if i < 10 goto loopend: return
    92. 92. Enter Loops0: iconst_01: istore_12: iload_13: bipush 105: if_icmpge 22System.out.println(“Hello”)16: iinc 1, 119: goto 222: return
    93. 93. Enter Loopsstart: iconst_0 1: istore_1loop: iload_1 3: bipush 10 5: if_icmpge end System.out.println(“Hello”) 16: iinc 1, 1 19: goto loopend: return
    94. 94. Enter Loopsstart: iconst_0 1: istore_1 int i = 0loop: iload_1 3: bipush 10 5: if_icmpge end System.out.println(“Hello”) 16: iinc 1, 1 19: goto loopend: return
    95. 95. Enter Loopsstart: iconst_0 1: istore_1loop: iload_1 3: bipush 10 i < 10 5: if_icmpge end System.out.println(“Hello”) 16: iinc 1, 1 19: goto loopend: return
    96. 96. Enter Loopsstart: iconst_0 1: istore_1loop: iload_1 3: bipush 10 5: if_icmpge end System.out.println(“Hello”) 16: iinc 1, 1 i++ 19: goto loopend: return
    97. 97. Enter Loopsstart: iconst_0 1: istore_1loop: iload_1 3: bipush 10 5: if_icmpge end System.out.println(“Hello”) 16: iinc 1, 1 19: goto loopend: return
    98. 98. Enter ASM LoopsLabel start = new Label();Label loop = new Label();Label end = new Label();// i = 0mv.visitLabel(start);mv.visitInsn(ICONST_0);mv.visitVarInsn(ISTORE, 1);
    99. 99. Enter ASM LoopsLabel start = new Label();Label loop = new Label();Label end = new Label();// i = 0mv.visitLabel(start);mv.visitInsn(ICONST_0);mv.visitVarInsn(ISTORE, 1);// i < 10mv.visitLabel(loop);mv.visitVarInsn(ILOAD, 1);mv.visitLdcInsn(10);mv.visitJumpInsn(IF_ICMPGE, end);
    100. 100. Enter ASM LoopsLabel start = new Label();Label loop = new Label();Label end = new Label(); //increment & continue the loop mv.visitIincInsn(1, 1);// i = 0 mv.visitJumpInsn(GOTO, loop);mv.visitLabel(start); mv.visitLabel(end);mv.visitInsn(ICONST_0);mv.visitVarInsn(ISTORE, 1);// i < 10mv.visitLabel(loop);mv.visitVarInsn(ILOAD, 1);mv.visitLdcInsn(10);mv.visitJumpInsn(IF_ICMPGE, end);
    101. 101. ClassWriter
    102. 102. geecon$ java HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello
    103. 103. ASMified ASMifierClassVisitormv = cw.visitMethod(ACC_PUBLIC, "getId", "(I)I", null, null);mv.visitCode();Label l0 = new Label();mv.visitLabel(l0);mv.visitLineNumber(16, l0);mv.visitVarInsn(ALOAD, 0);mv.visitFieldInsn(GETFIELD, "zt/asm/Items", "ids", "Ljava/util/List;"); java -cp asm-all-3.3.1.jar:asm-util-3.3.1.jar mv.visitVarInsn(ILOAD, 1); org.objectweb.asm.util.ASMifierClassVisitor mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "get", "(I)Ljava/lang/Object;"); Hello.classmv.visitTypeInsn(CHECKCAST, "java/lang/Integer");mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");mv.visitInsn(IRETURN);Label l1 = new Label();mv.visitLabel(l1);mv.visitLocalVariable("this", "Lzt/asm/Items;", null, l0, l1, 0);mv.visitLocalVariable("i", "I", null, l0, l1, 1);mv.visitMaxs(2, 2);mv.visitEnd();
    104. 104. Bytecodeinstrumentation Some magic for your own good
    105. 105. WAT!?Ninja.class Ninja.class’10101010101 1010101010111000101010 1110000101010101010001 1010101000100010001110 0001000111011011101011 11011101110
    106. 106. Who? Containers (Java EE, Spring) TerracottaJRebel Tapestry Byteman
    107. 107. How?• Add –javaagent to hook into class loading process• Implement ClassFileTransformer• Use bytecode manipulation libraries (Javassist, cglib, asm) to add any custom logic java.lang.instrument
    108. 108. How ? (2)• Use custom ClassLoader – Override ClassLoader#findClass – Use ClassReader(String) to read the class in and transform it via visitor chain – Call ClassLoader#defineClass explicitly with the result from the transformation step
    109. 109. java.lang.instrumentimport java.lang.instrument.ClassFileTransformer;import java.lang.instrument.Instrumentation;public class Agent {public static void premain(String args, Instrumentation inst) { inst.addTransformer(new ClassFileTransformer(), true); }public static void agentmain(String args, Instrumentation inst) { premain(args,inst); }}
    110. 110. java.lang.instrumentimport java.lang.instrument.ClassFileTransformer;import java.lang.instrument.Instrumentation;public class Agent {public static void premain(String args, Instrumentation inst) { inst.addTransformer(new ClassFileTransformer(), true); }public static void agentmain(String args, Instrumentation inst) { premain(args,inst); }}
    111. 111. java.lang.instrumentimport java.lang.instrument.ClassFileTransformer;import java.lang.instrument.Instrumentation;public class Agent {public static void premain(String args, Instrumentation inst) { inst.addTransformer(new ClassFileTransformer(), true); }public static void agentmain(String args, Instrumentation inst) { premain(args,inst); }} META-INF/MANIFEST.MF Premain-Class: Agent java –javaagent:agent.jar … Agent-Class: Agent
    112. 112. j.l.instrument.ClassFileTransformernew ClassFileTransformer() { public byte[] transform(ClassLoader loader, String className, Class<?>classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer){ ClassReader cr = new ClassReader(classfileBuffer); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); MyAdapter ca = new MyAdapter(cw); cr.accept(ca, ClassReader.EXPAND_FRAMES); return cw.toByteArray();}
    113. 113. j.l.instrument.ClassFileTransformernew ClassFileTransformer() { public byte[] transform(ClassLoader loader, String className, Class<?>classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer){ ClassReader cr = new ClassReader(classfileBuffer); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); MyAdapter ca = new MyAdapter(cw); cr.accept(ca, ClassReader.EXPAND_FRAMES); return cw.toByteArray();}
    114. 114. j.l.instrument.ClassFileTransformernew ClassFileTransformer() { public byte[] transform(ClassLoader loader, String className, Class<?>classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer){ ClassReader cr = new ClassReader(classfileBuffer); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); MyAdapter ca = new MyAdapter(cw); cr.accept(ca, ClassReader.EXPAND_FRAMES); return cw.toByteArray();}
    115. 115. public class MyClassLoader extends ClassLoader { protected Class findClass(String name) throws ClassNotFoundException { ClassReader cr = new ClassReader(name); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); MyClassAdapter ca = new MyClassAdapter(cw); cr.accept(ca, ClassReader.EXPAND_FRAMES); byte b[] = cw.toByteArray(); return defineClass(name, b, 0, b.length); }
    116. 116. SLIDESGOTO: IDESLIDESIDE: ASM DEMO
    117. 117. @antonarhipov anton@zeroturnaround.comhttps://github.com/antonarhipov/asmdemo
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×