SlideShare a Scribd company logo
Mastering Java Bytecode with ASM
Learn some bytecode to yourself!
whoami
Anton Arhipov
Java Dev / Product Lead
ZeroTurnaround, JRebel
Messing with bytecode since 2010


anton@zeroturnaround.com
@antonarhipov @javarebel
whoami
Anton Arhipov
Java Dev / Product Lead
ZeroTurnaround, JRebel
Messing with bytecode since 2010


anton@zeroturnaround.com
@antonarhipov @javarebel
Why Bytecode?
•   Know your platform!
•   Build your own JVM language?
•   Programming models (AOP, ORM)
•   Awesome tools (like JRebel )

... just bored?
Bytecode 101     Instrumentation API

       javap   ObjectWeb ASM
Bytecode 101
  Gentle introduction
Adding Two Values




A+B
Adding Two Values




A+B
AB+
Adding Two Values




A+B
AB+
Adding Two Values




A+B   PUSH A
                      A
AB+
Adding Two Values




A+B   PUSH 1
      PUSH 2
                      B
AB+                   A
Adding Two Values




A+B   PUSH 1
      PUSH 2
                      15
AB+   ADD
Adding Two Values




A+B   ICONST_1
      ICONST_2
                      15
AB+   IADD
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)
Model of
Execution
Enter JVM




JVM process
Enter Threads




Thread A    Thread B   Thread C   Thread D
Enter Frames
The Frame
Local variables
0 1 2        …    N
Operand stack

                  #1
                        Constant
                          Pool
Juggling The Stack
Juggling The Stack

dup                      A
pop                      B
swap
dup_x1
dup2_x1
Juggling The Stack

dup                      A
pop                      A
swap                     B
dup_x1
dup2_x1
Juggling The Stack

dup                      A
pop                      B
swap
dup_x1
dup2_x1
Juggling The Stack

dup                      B
pop                      A
swap
dup_x1
dup2_x1
Juggling The Stack

dup                      B
pop                      A
swap                     B
dup_x1
dup2_x1
Juggling The Stack

dup                      B
pop                      A
swap                     B
dup_x1                   B
dup2_x1                  A
Local Variables
Local Variables                         Stack
var      value                      depth     value

0
                      ldc "Hello"    0
                      astore_0
1                                    1
                      iconst_1
2                     astore_1       2

3                     aload_0        3

4                                    4
Local Variables                         Stack
var      value                      depth     value

0
                      ldc "Hello"    0       "Hello"
                      astore_0
1                                    1
                      iconst_1
2                     astore_1       2

3                     aload_0        3

4                                    4
Local Variables                         Stack
var      value                      depth     value

0
                      ldc "Hello"    0
        "Hello"
                      astore_0
1                                    1
                      iconst_1
2                     astore_1       2

3                     aload_0        3

4                                    4
Local Variables                         Stack
var      value                      depth     value

0
                      ldc "Hello"    0
        "Hello"                                     1
                      astore_0
1                                    1
                      iconst_1
2                     astore_1       2

3                     aload_0        3

4                                    4
Local Variables                         Stack
var      value                      depth     value

0
                      ldc "Hello"    0
        "Hello"
                      astore_0
1           1                        1
                      iconst_1
2                     astore_1       2

3                     aload_0        3

4                                    4
Local Variables                         Stack
var      value                      depth     value

0
                      ldc "Hello"    0
        "Hello"                              "Hello"
                      astore_0
1           1                        1
                      iconst_1
2                     astore_1       2

3                     aload_0        3

4                                    4
load
  Local
Variables           Stack
  Table

            store
Method Invoсation
Method Invocation

obj.method(param1, param2);
Method Invocation

obj.method(param1, param2);

      push obj
      push param1
      push param2
      invoke method
Method Invocation

obj.method(param1, param2);
                              obj
      push obj
      push param1
      push param2
      invoke method
Method Invocation

obj.method(param1, param2);
                              param1
      push obj                 obj
      push param1
      push param2
      invoke method
Method Invocation

obj.method(param1, param2);
                              param2
      push obj                param1
      push param1              obj
      push param2
      invoke method
Method Invocation

obj.method(param1, param2);
                              obj?
      push obj
      push param1
      push param2
      invoke method
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         invokevirtual plus
Operator Overloading

[int] A + B    [Foo] A + B
     push A       push A
     push B       push B
     iadd         invokevirtual plus
pop   push




 Stack
pop   push

            load
 Local
Variables            Stack
  Table


            store
pop   push

            load
 Local
Variables            Stack
  Table


            store
pop      push

            load
 Local
Variables                       Stack             invoke
  Table


            store                               pop push


                                 load

                    Local
                   Variables                   Stack
                     Table

                                 store
javap
The disassembler
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 
Mastering java bytecode with ASM - GeeCON 2012
C:workgeeconclasses>javap Hello -c
C:workgeeconclasses>javap Hello -c
Compiled 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
C:workgeeconclasses>javap Hello -c
Compiled 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
C:workgeeconclasses>javap Hello -c
Compiled 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
C:workgeeconclasses>javap Hello -c
Compiled 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
C:workgeeconclasses>javap Hello -c
Compiled 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
C:workgeeconclasses>javap Hello -c
Compiled 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

public 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
C:workgeeconclasses>javap Hello -c
Compiled 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 field
public 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
C:workgeeconclasses>javap Hello -c
Compiled 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

public 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
C:workgeeconclasses>javap Hello -c
Compiled 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

public 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
C:workgeeconclasses>javap Hello -c
Compiled 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

public 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
What’s #1,#2, etc ?
C:workgeeconclasses>javap Hello -c
Compiled 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

public 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
SLIDES
GOTO: IDE
SLIDES
IDE: JAVAP DEMO
ASM
The 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
ClassWriter

ClassWriter 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 Class

cv.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      boolean
  V      void
Type Descriptors



Lsome/Class;
Type Descriptors



[Lsome/Class;
Method Signatures

()V                      void foo()

(Ljava/lang/Object;)I    int foo(Object)

([Ljava/lang/String;)V   void main(String[])
Visit Method
MethodVisitor constructor =
  cv.visitMethod(ACC_PUBLIC,
  "<init>",
  "()V",
  null,
  null);
MethodVisitor mv = cv.visitMethod(
    ACC_PUBLIC + ACC_STATIC,
    "main",
    "([Ljava/lang/String;)V",
    null,
    null);
Visit Method
MethodVisitor 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);
Special Methods

• <init>
  –Constructor
• <clinit>
  –Static initializer
MethodVisitor
• Visit annotations
• Visit code
  – Bytecodes, local variables, line numbers, etc
• Visit maxs
  – Pass bogus values if COMPUTE_MAX
Constructor

c.visitVarInsn(ALOAD, 0);
c.visitMethodInsn(INVOKESPECIAL,
   "java/lang/Object", "<init>", "()V");
c.visitInsn(RETURN);
c.visitMaxs(0, 0);
Constructor

c.visitVarInsn(ALOAD, 0);
c.visitMethodInsn(INVOKESPECIAL,
   "java/lang/Object", "<init>", "()V");
c.visitInsn(RETURN);
c.visitMaxs(0, 0);
                           aload_0
                           invokespecial
                           return
public static void main()
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);
public static void main()
mv.visitFieldInsn(GETSTATIC,
      "java/lang/System", "out",
                                          getstatic
      "Ljava/io/PrintStream;");           ldc “Hello”
                                          invokevirtual
mv.visitLdcInsn("Hello");                 return


mv.visitMethodInsn(INVOKEVIRTUAL,
      "java/io/PrintStream", "println",
      "(Ljava/lang/String;)V");

mv.visitInsn(RETURN);
Enter Loops
Enter Loops


start:
  int i = 0
loop:
  print "Hello"
  i=i+1
  if i < 10 goto loop
end: return
Enter Loops


start:
  int i = 0         GOTO isn’t harmful ;)
loop:
  print "Hello"
  i=i+1
  if i < 10 goto loop
end: return
Enter Loops
0:    iconst_0
1:    istore_1
2:    iload_1
3:    bipush    10
5:    if_icmpge 22

System.out.println(“Hello”)

16: iinc 1, 1
19: goto 2
22: return
Enter Loops
start: iconst_0
  1: istore_1
loop: iload_1
  3: bipush     10
  5: if_icmpge end

 System.out.println(“Hello”)

 16: iinc 1, 1
 19: goto loop
end: return
Enter Loops
start: iconst_0
  1: istore_1           int i = 0
loop: iload_1
  3: bipush     10
  5: if_icmpge end

 System.out.println(“Hello”)

 16: iinc 1, 1
 19: goto loop
end: return
Enter Loops
start: iconst_0
  1: istore_1
loop: iload_1
  3: bipush     10      i < 10
  5: if_icmpge end

 System.out.println(“Hello”)

 16: iinc 1, 1
 19: goto loop
end: return
Enter Loops
start: iconst_0
  1: istore_1
loop: iload_1
  3: bipush     10
  5: if_icmpge end

 System.out.println(“Hello”)

 16: iinc 1, 1         i++
 19: goto loop
end: return
Enter Loops
start: iconst_0
  1: istore_1
loop: iload_1
  3: bipush     10
  5: if_icmpge end

 System.out.println(“Hello”)

 16: iinc 1, 1
 19: goto loop
end: return
Enter ASM Loops
Label start = new Label();
Label loop = new Label();
Label end = new Label();

// i = 0
mv.visitLabel(start);
mv.visitInsn(ICONST_0);
mv.visitVarInsn(ISTORE, 1);
Enter ASM Loops
Label start = new Label();
Label loop = new Label();
Label end = new Label();

// i = 0
mv.visitLabel(start);
mv.visitInsn(ICONST_0);
mv.visitVarInsn(ISTORE, 1);

// i < 10
mv.visitLabel(loop);
mv.visitVarInsn(ILOAD, 1);
mv.visitLdcInsn(10);
mv.visitJumpInsn(IF_ICMPGE, end);
Enter ASM Loops
Label 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 < 10
mv.visitLabel(loop);
mv.visitVarInsn(ILOAD, 1);
mv.visitLdcInsn(10);
mv.visitJumpInsn(IF_ICMPGE, end);
Mastering java bytecode with ASM - GeeCON 2012
ClassWriter
geecon$ java Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
ASMified
     ASMifierClassVisitor
mv = 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.class
mv.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();
Bytecode
instrumentation
 Some magic for your own good
WAT!?
Ninja.class           Ninja.class’
10101010101           10101010101
11000101010           11100001010
10101010001           10101010001
00010001110           00010001110
11011101011           11011101110
Who?

          Containers (Java EE, Spring)

                   Terracotta
JRebel

                         Tapestry
         Byteman
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
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
java.lang.instrument

import 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); }
}
java.lang.instrument

import 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); }
}
java.lang.instrument

import 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
j.l.instrument.ClassFileTransformer
new 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();
}
j.l.instrument.ClassFileTransformer
new 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();
}
j.l.instrument.ClassFileTransformer
new 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();
}
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);
 }
SLIDES
GOTO: IDE
SLIDES
IDE: ASM DEMO
@antonarhipov
    anton@zeroturnaround.com
https://github.com/antonarhipov/asmdemo

More Related Content

PPTX
Mastering Java Bytecode With ASM - 33rd degree, 2012
PPTX
All you need to know about the JavaScript event loop
PPTX
java memory management & gc
KEY
JavaOne 2011 - JVM Bytecode for Dummies
PDF
Svelte JS introduction
KEY
2장. Runtime Data Areas
PPT
JDBC – Java Database Connectivity
PDF
[수정본] 우아한 객체지향
Mastering Java Bytecode With ASM - 33rd degree, 2012
All you need to know about the JavaScript event loop
java memory management & gc
JavaOne 2011 - JVM Bytecode for Dummies
Svelte JS introduction
2장. Runtime Data Areas
JDBC – Java Database Connectivity
[수정본] 우아한 객체지향

What's hot (20)

PPTX
cours javascript.pptx
PPT
CSS
PPTX
JavaScript Event Loop
PPTX
Express js
PPT
JavaScript
PPT
Collections Framework
PDF
Object Oriented Programming in JavaScript
PPT
C++ oop
PPTX
Introduction Dart
PDF
NodeJS for Beginner
PPTX
Java Virtual Machine, Call stack, Java Byte Code
PPT
Java EE and Spring Side-by-Side
KEY
HTML CSS & Javascript
PDF
Spring Boot
PPT
Java Script ppt
PPTX
Introduction to NodeJS
PDF
ES6 presentation
PPTX
Spring Boot
PDF
Introduction to SQLAlchemy ORM
PPTX
Java packages
cours javascript.pptx
CSS
JavaScript Event Loop
Express js
JavaScript
Collections Framework
Object Oriented Programming in JavaScript
C++ oop
Introduction Dart
NodeJS for Beginner
Java Virtual Machine, Call stack, Java Byte Code
Java EE and Spring Side-by-Side
HTML CSS & Javascript
Spring Boot
Java Script ppt
Introduction to NodeJS
ES6 presentation
Spring Boot
Introduction to SQLAlchemy ORM
Java packages
Ad

Similar to Mastering java bytecode with ASM - GeeCON 2012 (18)

PDF
LatJUG. Java Bytecode Fundamentals
PDF
tutorial5
PDF
tutorial5
PDF
Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...
PDF
Javascript engine performance
PDF
Scala introduction
PPT
PPTX
Java Bytecode Fundamentals - JUG.lv
PDF
NoSQL - how it works (@pavlobaron)
KEY
2011.06.20 stratified-btree
KEY
Charles nutter star techconf 2011 - jvm languages
PDF
From Hand To Mouth (@pavlobaron)
KEY
High Performance Ruby - Golden Gate RubyConf 2012
PPTX
Java Bytecode: Passing Parameters
PDF
The Gremlin in the Graph
PDF
Virtual machine and javascript engine
PDF
A Guide to the Post Relational Revolution
PDF
Yapc asia 2011_zigorou
LatJUG. Java Bytecode Fundamentals
tutorial5
tutorial5
Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...
Javascript engine performance
Scala introduction
Java Bytecode Fundamentals - JUG.lv
NoSQL - how it works (@pavlobaron)
2011.06.20 stratified-btree
Charles nutter star techconf 2011 - jvm languages
From Hand To Mouth (@pavlobaron)
High Performance Ruby - Golden Gate RubyConf 2012
Java Bytecode: Passing Parameters
The Gremlin in the Graph
Virtual machine and javascript engine
A Guide to the Post Relational Revolution
Yapc asia 2011_zigorou
Ad

More from Anton Arhipov (20)

PDF
JavaZone 2022 - Building Kotlin DSL.pdf
PDF
Idiomatic kotlin
PDF
TechTrain 2019 - (Не)адекватное техническое интервью
PDF
Build pipelines with TeamCity
PDF
Build pipelines with TeamCity
PDF
Devoxx Ukraine 2018 - Kotlin DSL in under an hour
PDF
GeeCON Prague 2018 - Kotlin DSL in under an hour
PDF
Build pipelines with TeamCity and Kotlin DSL
PDF
Build pipelines with TeamCity
PDF
JavaDay Kiev 2017 - Integration testing with TestContainers
PDF
GeeCON Prague 2017 - TestContainers
PDF
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
PDF
JavaOne 2017 - TestContainers: integration testing without the hassle
PDF
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
PDF
JavaZone 2017 - The Hitchhiker’s guide to Java class reloading
PDF
JUG.ua 20170225 - Java bytecode instrumentation
PDF
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
PDF
GeeCON 2017 - TestContainers. Integration testing without the hassle
PDF
JEEConf 2017 - The hitchhiker’s guide to Java class reloading
PDF
JEEConf 2017 - Having fun with Javassist
JavaZone 2022 - Building Kotlin DSL.pdf
Idiomatic kotlin
TechTrain 2019 - (Не)адекватное техническое интервью
Build pipelines with TeamCity
Build pipelines with TeamCity
Devoxx Ukraine 2018 - Kotlin DSL in under an hour
GeeCON Prague 2018 - Kotlin DSL in under an hour
Build pipelines with TeamCity and Kotlin DSL
Build pipelines with TeamCity
JavaDay Kiev 2017 - Integration testing with TestContainers
GeeCON Prague 2017 - TestContainers
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - TestContainers: integration testing without the hassle
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaZone 2017 - The Hitchhiker’s guide to Java class reloading
JUG.ua 20170225 - Java bytecode instrumentation
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
GeeCON 2017 - TestContainers. Integration testing without the hassle
JEEConf 2017 - The hitchhiker’s guide to Java class reloading
JEEConf 2017 - Having fun with Javassist

Recently uploaded (20)

PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
KodekX | Application Modernization Development
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PPT
Teaching material agriculture food technology
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
CIFDAQ's Market Insight: SEC Turns Pro Crypto
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
KodekX | Application Modernization Development
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Teaching material agriculture food technology
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Chapter 3 Spatial Domain Image Processing.pdf
Building Integrated photovoltaic BIPV_UPV.pdf
NewMind AI Weekly Chronicles - August'25 Week I
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
Reach Out and Touch Someone: Haptics and Empathic Computing
CIFDAQ's Market Insight: SEC Turns Pro Crypto
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Unlocking AI with Model Context Protocol (MCP)
Spectral efficient network and resource selection model in 5G networks
Mobile App Security Testing_ A Comprehensive Guide.pdf
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Diabetes mellitus diagnosis method based random forest with bat algorithm
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...

Mastering java bytecode with ASM - GeeCON 2012

  • 1. Mastering Java Bytecode with ASM Learn some bytecode to yourself!
  • 2. whoami Anton Arhipov Java Dev / Product Lead ZeroTurnaround, JRebel Messing with bytecode since 2010 [email protected] @antonarhipov @javarebel
  • 3. whoami Anton Arhipov Java Dev / Product Lead ZeroTurnaround, JRebel Messing with bytecode since 2010 [email protected] @antonarhipov @javarebel
  • 4. Why Bytecode? • Know your platform! • Build your own JVM language? • Programming models (AOP, ORM) • Awesome tools (like JRebel ) ... just bored?
  • 5. Bytecode 101 Instrumentation API javap ObjectWeb ASM
  • 6. Bytecode 101 Gentle introduction
  • 10. Adding Two Values A+B PUSH A A AB+
  • 11. Adding Two Values A+B PUSH 1 PUSH 2 B AB+ A
  • 12. Adding Two Values A+B PUSH 1 PUSH 2 15 AB+ ADD
  • 13. Adding Two Values A+B ICONST_1 ICONST_2 15 AB+ IADD
  • 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)
  • 17. Enter Threads Thread A Thread B Thread C Thread D
  • 19. The Frame Local variables 0 1 2 … N Operand stack #1 Constant Pool
  • 21. Juggling The Stack dup A pop B swap dup_x1 dup2_x1
  • 22. Juggling The Stack dup A pop A swap B dup_x1 dup2_x1
  • 23. Juggling The Stack dup A pop B swap dup_x1 dup2_x1
  • 24. Juggling The Stack dup B pop A swap dup_x1 dup2_x1
  • 25. Juggling The Stack dup B pop A swap B dup_x1 dup2_x1
  • 26. Juggling The Stack dup B pop A swap B dup_x1 B dup2_x1 A
  • 28. Local Variables Stack var value depth value 0 ldc "Hello" 0 astore_0 1 1 iconst_1 2 astore_1 2 3 aload_0 3 4 4
  • 29. Local Variables Stack var value depth value 0 ldc "Hello" 0 "Hello" astore_0 1 1 iconst_1 2 astore_1 2 3 aload_0 3 4 4
  • 30. Local Variables Stack var value depth value 0 ldc "Hello" 0 "Hello" astore_0 1 1 iconst_1 2 astore_1 2 3 aload_0 3 4 4
  • 31. Local Variables Stack var value depth value 0 ldc "Hello" 0 "Hello" 1 astore_0 1 1 iconst_1 2 astore_1 2 3 aload_0 3 4 4
  • 32. Local Variables Stack var value depth value 0 ldc "Hello" 0 "Hello" astore_0 1 1 1 iconst_1 2 astore_1 2 3 aload_0 3 4 4
  • 33. Local Variables Stack var value depth value 0 ldc "Hello" 0 "Hello" "Hello" astore_0 1 1 1 iconst_1 2 astore_1 2 3 aload_0 3 4 4
  • 34. load Local Variables Stack Table store
  • 37. Method Invocation obj.method(param1, param2); push obj push param1 push param2 invoke method
  • 38. Method Invocation obj.method(param1, param2); obj push obj push param1 push param2 invoke method
  • 39. Method Invocation obj.method(param1, param2); param1 push obj obj push param1 push param2 invoke method
  • 40. Method Invocation obj.method(param1, param2); param2 push obj param1 push param1 obj push param2 invoke method
  • 41. Method Invocation obj.method(param1, param2); obj? push obj push param1 push param2 invoke method
  • 43. Operator Overloading [int] A + B [Foo] A.plus(B)
  • 44. Operator Overloading [int] A + B [Foo] A.plus(B) push A push A push B push B iadd invokevirtual plus
  • 45. Operator Overloading [int] A + B [Foo] A + B push A push A push B push B iadd invokevirtual plus
  • 46. pop push Stack
  • 47. pop push load Local Variables Stack Table store
  • 48. pop push load Local Variables Stack Table store
  • 49. pop push load Local Variables Stack invoke Table store pop push load Local Variables Stack Table store
  • 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 
  • 54. C:workgeeconclasses>javap Hello -c Compiled 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
  • 55. C:workgeeconclasses>javap Hello -c Compiled 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
  • 56. C:workgeeconclasses>javap Hello -c Compiled 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
  • 57. C:workgeeconclasses>javap Hello -c Compiled 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
  • 58. C:workgeeconclasses>javap Hello -c Compiled 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
  • 59. C:workgeeconclasses>javap Hello -c Compiled 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 public 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. C:workgeeconclasses>javap Hello -c Compiled 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 field public 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
  • 61. C:workgeeconclasses>javap Hello -c Compiled 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 public 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
  • 62. C:workgeeconclasses>javap Hello -c Compiled 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 public 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
  • 63. C:workgeeconclasses>javap Hello -c Compiled 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 public 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. What’s #1,#2, etc ? C:workgeeconclasses>javap Hello -c Compiled 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 public 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
  • 66. ASM The de facto standard for bytecode manipulation
  • 67. ASM • “All purpose bytecode manipulation and analysis framework” • De facto standard bytecode library • http://asm.ow2.org
  • 68. Basic Process • Construct ClassWriter • Stack up the visitors for: • annotations, methods, fields, etc • Write out bytes
  • 70. ClassWriter ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
  • 71. COMPUTE_*** • COMPUTE_MAXS –ASM will calculate max stack/local vars • COMPUTE_FRAMES –ASM will calculate Java 6 stack map
  • 72. Visit Class cv.visit(V1_6, ACC_PUBLIC, "X", null, "java/lang/Object", null);
  • 73. Opcodes • Interface full of constants –Bytecodes –Visibility modifiers –Java versions –Other stuff
  • 74. ACC_*** • Some you know –ACC_PUBLIC, ACC_ABSTRACT, etc • Some you (probably) don’t –ACC_BRIDGE, ACC_SYNTHETIC
  • 75. Class Names "java/lang/Object" packageClass.replaceAll('.', '/')
  • 77. Type Descriptors B byte C char S string I int J long F float D double Z boolean V void
  • 80. Method Signatures ()V void foo() (Ljava/lang/Object;)I int foo(Object) ([Ljava/lang/String;)V void main(String[])
  • 81. Visit Method MethodVisitor constructor = cv.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); MethodVisitor mv = cv.visitMethod( ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
  • 82. Visit Method MethodVisitor 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);
  • 83. Special Methods • <init> –Constructor • <clinit> –Static initializer
  • 84. MethodVisitor • Visit annotations • Visit code – Bytecodes, local variables, line numbers, etc • Visit maxs – Pass bogus values if COMPUTE_MAX
  • 85. Constructor c.visitVarInsn(ALOAD, 0); c.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); c.visitInsn(RETURN); c.visitMaxs(0, 0);
  • 86. Constructor c.visitVarInsn(ALOAD, 0); c.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); c.visitInsn(RETURN); c.visitMaxs(0, 0); aload_0 invokespecial return
  • 88. 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);
  • 89. public static void main() mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", getstatic "Ljava/io/PrintStream;"); ldc “Hello” invokevirtual mv.visitLdcInsn("Hello"); return mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); mv.visitInsn(RETURN);
  • 91. Enter Loops start: int i = 0 loop: print "Hello" i=i+1 if i < 10 goto loop end: return
  • 92. Enter Loops start: int i = 0 GOTO isn’t harmful ;) loop: print "Hello" i=i+1 if i < 10 goto loop end: return
  • 93. Enter Loops 0: iconst_0 1: istore_1 2: iload_1 3: bipush 10 5: if_icmpge 22 System.out.println(“Hello”) 16: iinc 1, 1 19: goto 2 22: return
  • 94. Enter Loops start: iconst_0 1: istore_1 loop: iload_1 3: bipush 10 5: if_icmpge end System.out.println(“Hello”) 16: iinc 1, 1 19: goto loop end: return
  • 95. Enter Loops start: iconst_0 1: istore_1 int i = 0 loop: iload_1 3: bipush 10 5: if_icmpge end System.out.println(“Hello”) 16: iinc 1, 1 19: goto loop end: return
  • 96. Enter Loops start: iconst_0 1: istore_1 loop: iload_1 3: bipush 10 i < 10 5: if_icmpge end System.out.println(“Hello”) 16: iinc 1, 1 19: goto loop end: return
  • 97. Enter Loops start: iconst_0 1: istore_1 loop: iload_1 3: bipush 10 5: if_icmpge end System.out.println(“Hello”) 16: iinc 1, 1 i++ 19: goto loop end: return
  • 98. Enter Loops start: iconst_0 1: istore_1 loop: iload_1 3: bipush 10 5: if_icmpge end System.out.println(“Hello”) 16: iinc 1, 1 19: goto loop end: return
  • 99. Enter ASM Loops Label start = new Label(); Label loop = new Label(); Label end = new Label(); // i = 0 mv.visitLabel(start); mv.visitInsn(ICONST_0); mv.visitVarInsn(ISTORE, 1);
  • 100. Enter ASM Loops Label start = new Label(); Label loop = new Label(); Label end = new Label(); // i = 0 mv.visitLabel(start); mv.visitInsn(ICONST_0); mv.visitVarInsn(ISTORE, 1); // i < 10 mv.visitLabel(loop); mv.visitVarInsn(ILOAD, 1); mv.visitLdcInsn(10); mv.visitJumpInsn(IF_ICMPGE, end);
  • 101. Enter ASM Loops Label 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 < 10 mv.visitLabel(loop); mv.visitVarInsn(ILOAD, 1); mv.visitLdcInsn(10); mv.visitJumpInsn(IF_ICMPGE, end);
  • 105. ASMified ASMifierClassVisitor mv = 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.class mv.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();
  • 107. WAT!? Ninja.class Ninja.class’ 10101010101 10101010101 11000101010 11100001010 10101010001 10101010001 00010001110 00010001110 11011101011 11011101110
  • 108. Who? Containers (Java EE, Spring) Terracotta JRebel Tapestry Byteman
  • 109. 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
  • 110. 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
  • 111. java.lang.instrument import 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); } }
  • 112. java.lang.instrument import 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); } }
  • 113. java.lang.instrument import 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
  • 114. j.l.instrument.ClassFileTransformer new 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. j.l.instrument.ClassFileTransformer new 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(); }
  • 116. j.l.instrument.ClassFileTransformer new 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(); }
  • 117. 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); }
  • 119. @antonarhipov [email protected] https://github.com/antonarhipov/asmdemo

Editor's Notes

  • #5: 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 
  • #6: This presentation provides some pointers to the subject
  • #51: 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.
  • #69: 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.
  • #71: 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
  • #106: ... using ASMifierClassVisitor (ASMifier in ASM4). The output is rather noisy, with all the labels,but the noise is easy to remove.