latjug. java bytecode fundamentals
DESCRIPTION
Java Bytecode Fundamentals Anton Arhipov [Estonia] http://goo.gl/GO6Mm Java User Group Latvia March 2011 http://goo.gl/77MhTTRANSCRIPT
Java Bytecode
Fundamentals
JUG.LV 2011, Riga
whoami
http://arhipov.blogspot.com
@antonarhipov
@javarebel
Anton Arhipov ZeroTurnaround
JRebel
who-are-you?
1 + 2
1 + 2 1 2
+
1 + 2 1 2
+
1 2 +
1 + 2 1 2
+
1 2 +
1 + 2 1 2
+
1 2 + PUSH 1 1
1 + 2 1 2
+
1 2 + PUSH 1
PUSH 2 2 1
1 + 2 1 2
+
1 2 + PUSH 1
PUSH 2
ADD
3
1 + 2 1 2
+
1 2 + ICONST_1
ICONST_2
IADD
3
? = 1 + 2
Byte Code
One-byte instructions
256 possible opcodes
~200 in use
Byte Code
One-byte instructions
256 possible opcodes
~200 in use
The Master Plan
javap
Stack Machine
Objects and Methods
Flow Control
javap
Java class file disassembler
Used with no options shows class
structure only
Methods, superclass, interfaces, etc
-c – shows the bytecode
-private – shows all classes and members
-s – prints internal types signatures
-l – prints lines numbers and local variable
tables
C:\work\jug\classes>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:\work\jug\classes>javap Hello -verbose Compiled from "Hello.java“
public class Hello extends java.lang.Object
SourceFile: "Hello.java"
minor version: 0
major version: 50
Constant pool:
const #1 = Method #6.#20; // java/lang/Object."<init>":()V
const #2 = Field #21.#22; // java/lang/System.out:Ljava/io/PrintStream;
const #3 = String #23; // Hello, World!
const #4 = Method #24.#25; // java/io/PrintStream.println:(Ljava/lang/String;)V
const #5 = class #26; // Hello
const #6 = class #27; // java/lang/Object
const #7 = Asciz <init>;
const #8 = Asciz ()V;
C:\work\jug\classes>javap Hello -verbose …
public Hello();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LHello;
C:\work\jug\classes>javap Hello -verbose …
public static void main(java.lang.String[]);
Code:
Stack=2, Locals=1, Args_size=1
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
8: return
LineNumberTable:
line 4: 0
line 5: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 args [Ljava/lang/String;
Stack Machine
JVM is a stack-based machine
Each thread has a stack
Stack stores frames
Frame is created on method invocation
Frame:
Operand stack
Array of local variables
Frame
public java.lang.String getName();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: getfield #2; //Field name:Ljava/lang/String;
4: areturn
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LGet;
public java.lang.String getName();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: getfield #2; //Field name:Ljava/lang/String;
4: areturn
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LGet;
aload_0 getfield 00 02 areturn
0 1 2 3 4
public java.lang.String getName();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: getfield #2; //Field name:Ljava/lang/String;
4: areturn
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LGet;
2A B4 00 02 B0
0 1 2 3 4
public java.lang.String getName();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: getfield #2; //Field name:Ljava/lang/String;
4: areturn
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LGet;
public java.lang.String getName();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: getfield #2; //Field name:Ljava/lang/String;
4: areturn
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LGet;
public java.lang.String getName();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: getfield #2; //Field name:Ljava/lang/String;
4: areturn
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LGet;
Stack Operations
A B
dup
pop
swap
dup_x1
dup_x2
Stack Operations
A
B
dup
pop
swap
dup_x1
dup_x2
A
Stack Operations
dup
pop
swap
dup_x1
dup_x2
A B
Stack Operations
dup
pop
swap
dup_x1
dup_x2
A B
Stack Operations
dup
pop
swap
dup_x1
dup_x2
A B
B
Stack Operations
dup
pop
swap
dup_x1
dup_x2
A B
B B A
Local Variables
Local Variables
public int calculate(int);
Code:
Stack=2, Locals=2, Args_size=2
…
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LLocalVariables;
0 5 1 value I
Local Variables
public int calculate(int);
Code:
Stack=2, Locals=2, Args_size=2
…
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LLocalVariables;
0 5 1 value I
Local Variables
public int calculate(int);
Code:
Stack=2, Locals=2, Args_size=2
…
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LLocalVariables;
0 5 1 value I
Local Variables
public int calculate(int);
Code:
Stack=2, Locals=2, Args_size=2
…
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LLocalVariables;
0 5 1 value I
The table
maps
numbers to
names
Local Variables
public int calculate(int);
Code:
Stack=2, Locals=2, Args_size=2
…
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LLocalVariables;
0 5 1 value I
Sized explicitly
Local Variables
ldc "Hello"
astore_0
iconst_1
astore_1
aload_0
depth value
Stack
var value
Local Variables
0
1
2
3
4
0
1
2
3
4
Local Variables
ldc "Hello"
astore_0
iconst_1
astore_1
aload_0
depth value
Stack
var value
Local Variables
"Hello" 0
1
2
3
4
0
1
2
3
4
Local Variables
ldc "Hello"
astore_0
iconst_1
astore_1
aload_0
depth value
Stack
var value
Local Variables
"Hello" 0
1
2
3
4
0
1
2
3
4
Local Variables
ldc "Hello"
astore_0
iconst_1
astore_1
aload_0
depth value
Stack
var value
Local Variables
"Hello" 0
1
2
3
4
0
1
2
3
4
1
Local Variables
ldc "Hello"
astore_0
iconst_1
astore_1
aload_0
depth value
Stack
var value
Local Variables
"Hello" 0
1
2
3
4
0
1
2
3
4
1
Local Variables
ldc "Hello"
astore_0
iconst_1
astore_1
aload_0
depth value
Stack
var value
Local Variables
"Hello" 0
1
2
3
4
0
1
2
3
4
1
"Hello"
Local Variables & Stack
Stack Local
Variables
Table
store
load
Object Initialization
new
<init>
<clinit> Instance initialization method
Class and interface
initialization method
Object Initialization: static {}
static {};
Code:
0: iconst_1
1: putstatic #2; //Field a:I
4: iconst_2
5: putstatic #3; //Field b:I
8: return
Object Initialization: static {}
static {};
Code:
0: iconst_1
1: putstatic #2; //Field a:I
4: iconst_2
5: putstatic #3; //Field b:I
8: return
<clinit>
Object Initialization: new
public Initializer();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: new #2; //class java/lang/Object
8: dup
9: invokespecial #1; //Method java/lang/Object."<init>":()V
12: putfield #3; //Field o:Ljava/lang/Object;
15: return
Object Initialization: new
public Initializer();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: new #2; //class java/lang/Object
8: dup
9: invokespecial #1; //Method java/lang/Object."<init>":()V
12: putfield #3; //Field o:Ljava/lang/Object;
15: return
Object Initialization: {}
Object Initialization: {}
Object Initialization: {}
public Initializer(int);
Code:
0: aload_0
1: invokespecial #1; // ..<init>
4: aload_0
5: iconst_1
6: putfield #2; //Field a:I
9: aload_0
10: iconst_2
11: putfield #3; //Field c:I
14: aload_0
15: iload_1
16: putfield #4; //Field b:I
19: return
Method Invocation
invokestatic
invokeinterface
invokevirtual
invokespecial
invokedynamic
Parameter Passing
Parameter Passing
parameter
return
value
0: aload_0
1: invokespecial #2;
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3;
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
Stack
1
2
3
var value
0: aload_1
1: invokevirtual #8;
4: iconst_1
5: iadd
6: invokestatic #7;
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
0: aload_0
1: invokespecial #2;
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3;
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
1
2
3
var value
0: aload_1
1: invokevirtual #8;
4: iconst_1
5: iadd
6: invokestatic #7;
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
this
Stack
0: aload_0
1: invokespecial #2; //createRandomValue()
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3;
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
1
2
3
var value
0: aload_1
1: invokevirtual #8;
4: iconst_1
5: iadd
6: invokestatic #7;
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
objectref
Stack
0: aload_0
1: invokespecial #2;
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3;
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
1
2
3
var value
0: aload_1
1: invokevirtual #8;
4: iconst_1
5: iadd
6: invokestatic #7;
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
objectref
Stack
0: aload_0
1: invokespecial #2;
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3;
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
1
2
3
var value
0: aload_1
1: invokevirtual #8;
4: iconst_1
5: iadd
6: invokestatic #7;
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
this
objectref
Stack
0: aload_0
1: invokespecial #2;
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3;
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
1
2
3
var value
0: aload_1
1: invokevirtual #8;
4: iconst_1
5: iadd
6: invokestatic #7;
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
this
objectref
objectref
Stack
0: aload_0
1: invokespecial #2;
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3; //incValue
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
1
2
3
var value
0: aload_1
1: invokevirtual #8;
4: iconst_1
5: iadd
6: invokestatic #7;
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
objectref
objectref
Stack
0: aload_0
1: invokespecial #2;
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3; //incValue
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
1
2
3
var value
0: aload_1
1: invokevirtual #8;
4: iconst_1
5: iadd
6: invokestatic #7;
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
objectref
objectref
objectref
Stack
0: aload_0
1: invokespecial #2;
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3; //incValue
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
1
2
3
var value
0: aload_1
1: invokevirtual #8; // Integer.intValue:()
4: iconst_1
5: iadd
6: invokestatic #7;
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
objectref
objectref
X
Stack
0: aload_0
1: invokespecial #2;
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3; //incValue
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
1
2
3
var value
0: aload_1
1: invokevirtual #8;
4: iconst_1
5: iadd
6: invokestatic #7;
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
objectref
objectref
1
X
Stack
0: aload_0
1: invokespecial #2;
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3; //incValue
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
1
2
3
var value
0: aload_1
1: invokevirtual #8;
4: iconst_1
5: iadd
6: invokestatic #7;
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
objectref
objectref
X + 1
Stack
0: aload_0
1: invokespecial #2;
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3; //incValue
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
1
2
3
var value
0: aload_1
1: invokevirtual #8;
4: iconst_1
5: iadd
6: invokestatic #7; //Integer.valueOf
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
objectref
objectref
objectref
Stack
0: aload_0
1: invokespecial #2;
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3; //incValue
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
1
2
3
var value
0: aload_1
1: invokevirtual #8;
4: iconst_1
5: iadd
6: invokestatic #7;
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
objectref
objectref
objectref
Stack
0: aload_0
1: invokespecial #2;
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3;
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
1
2
3
var value
0: aload_1
1: invokevirtual #8;
4: iconst_1
5: iadd
6: invokestatic #7;
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
objectref
objectref
Stack
0: aload_0
1: invokespecial #2;
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3;
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
1
2
3
var value
0: aload_1
1: invokevirtual #8;
4: iconst_1
5: iadd
6: invokestatic #7;
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
objectref
Stack
0: aload_0
1: invokespecial #2;
4: astore_1
5: aload_0
6: aload_1
7: invokespecial #3;
10: areturn
depth value
1
2
3
4
5
6
1
2
3
var value
Local Variables
1
2
3
var value
0: aload_1
1: invokevirtual #8;
4: iconst_1
5: iadd
6: invokestatic #7;
9: areturn
private java.lang.Integer incValue(java.lang.Integer);
public java.lang.Object execute();
objectref
Stack
Flow Control
Flow Control
GOTO
public int decide(int);
Code:
0: iload_1
1: bipush 10
3: if_icmpge 8
6: iconst_0
7: ireturn
8: bipush 100
10: ireturn
1
2
3
depth value
Stack
public int decide(int);
Code:
0: iload_1
1: bipush 10
3: if_icmpge 8
6: iconst_0
7: ireturn
8: bipush 100
10: ireturn
1
2
3
depth value
Stack
a
public int decide(int);
Code:
0: iload_1
1: bipush 10
3: if_icmpge 8
6: iconst_0
7: ireturn
8: bipush 100
10: ireturn
1
2
3
depth value
Stack
10 a
public int decide(int);
Code:
0: iload_1
1: bipush 10
3: if_icmpge 8
6: iconst_0
7: ireturn
8: bipush 100
10: ireturn
1
2
3
depth value
Stack
10 a
public int decide(int);
Code:
0: iload_1
1: bipush 10
3: if_icmpge 8
6: iconst_0
7: ireturn
8: bipush 100
10: ireturn
1
2
3
depth value
Stack
public int decide(int);
Code:
0: iload_1
1: bipush 10
3: if_icmpge 8
6: iconst_0
7: ireturn
8: bipush 100
10: ireturn
1
2
3
depth value
Stack
100
public int decide(int);
Code:
0: iload_1
1: bipush 10
3: if_icmpge 8
6: iconst_0
7: ireturn
8: bipush 100
10: ireturn
1
2
3
depth value
Stack
100
public int decide(int);
Code:
0: iload_1
1: bipush 10
3: if_icmpge 8
6: iconst_0
7: ireturn
8: bipush 100
10: ireturn
1
2
3
depth value
Stack
http://arhipov.blogspot.com
@antonarhipov
@javarebel