Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

bytecode manipulation
... with cglib and ASM
05.2014/Pawel Koperek
why?
bytecode sample
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Woohoo!");
    }
}
$ javac HelloWorld.java
00000000  ca fe ba be 00 00 00 33  00 15 0a 00 04 00 11 09  |.......3........|
00000010  00 03 00 12 07 00 13 07  00 14 01 00 05 66 69 65  |.............fie|
00000020  6c 64 01 00 01 49 01 00  06 3c 69 6e 69 74 3e 01  |ld...I...<init>.|
00000030  00 03 28 29 56 01 00 04  43 6f 64 65 01 00 0f 4c  |..()V...Code...L|
00000040  69 6e 65 4e 75 6d 62 65  72 54 61 62 6c 65 01 00  |ineNumberTable..|
00000050  08 67 65 74 46 69 65 6c  64 01 00 03 28 29 49 01  |.getField...()I.|
00000060  00 08 73 65 74 46 69 65  6c 64 01 00 04 28 49 29  |..setField...(I)|
00000070  56 01 00 0a 53 6f 75 72  63 65 46 69 6c 65 01 00  |V...SourceFile..|
00000080  0d 4e 65 77 43 6c 61 73  73 2e 6a 61 76 61 0c 00  |.NewClass.java..|
00000090  07 00 08 0c 00 05 00 06  01 00 08 4e 65 77 43 6c  |...........NewCl|
000000a0  61 73 73 01 00 10 6a 61  76 61 2f 6c 61 6e 67 2f  |ass...java/lang/|
000000b0  4f 62 6a 65 63 74 00 21  00 03 00 04 00 00 00 01  |Object.!........|
000000c0  00 02 00 05 00 06 00 00  00 03 00 01 00 07 00 08  |................|
000000d0  00 01 00 09 00 00 00 1d  00 01 00 01 00 00 00 05  |................|
000000e0  2a b7 00 01 b1 00 00 00  01 00 0a 00 00 00 06 00  |*...............|
000000f0  01 00 00 00 01 00 01 00  0b 00 0c 00 01 00 09 00  |................|
00000100  00 00 1d 00 01 00 01 00  00 00 05 2a b4 00 02 ac  |...........*....|
00000110  00 00 00 01 00 0a 00 00  00 06 00 01 00 00 00 05  |................|
00000120  00 01 00 0d 00 0e 00 01  00 09 00 00 00 22 00 02  |............."..|
00000130  00 02 00 00 00 06 2a 1b  b5 00 02 b1 00 00 00 01  |......*.........|
00000140  00 0a 00 00 00 0a 00 02  00 00 00 09 00 05 00 0a  |................|
00000150  00 01 00 0f 00 00 00 02  00 10                    |..........|
$ javap -c HelloWorld.class
public class HelloWorld {
  public HelloWorld();
    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 Woohoo!
       5: invokevirtual #4 
                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return
}
pushes "this" on stack
#1 refers to Constant Pool

invokes a "special" method (constructors, initialization blocks, private methods)
explicit return
retrieves value of static field and pushes on stack
pushes constant from Constant Pool on stack
invokes a virtual method (considers method overriding)
intercept a method
class ClassToBeIntercepted {

    public void toCallOne() {
        System.out.println("toCallOne");
    }

    public void toCallTwo() {
        System.out.println("toCallTwo");
    }
}
create new class
public class NewClass {
    private int field;

    public int getField() {
        return field;
    }

    public void setField(int field) {
        this.field = field;
    }
}
override a private method in a final class
public final class FinalClass {

    private void hardToCallMe() {
        System.out.println("inside hardToCallMe");
    }

    public void callMe() {
        System.out.println("inside callMe");
        hardToCallMe(); 
    }
}
good practices
  • when possible - use higher level libraries (cglib)
  • write as much as possible in Java (invoke methods in instrumentation code only)
  • don't write all of ASM code by yourself: write it in pure Java and use javap or ASMifier
questions?
thanks!

Use a spacebar or arrow keys to navigate