Java Bytecode for Discriminating Developers - JavaZone 2011
-
Upload
anton-arhipov -
Category
Technology
-
view
7.177 -
download
0
Transcript of Java Bytecode for Discriminating Developers - JavaZone 2011
Java Bytecode for
Discriminating Developers
JavaZone’11, Oslo
whoami
http://arhipov.blogspot.com
@antonarhipov
@javarebel
Anton Arhipov Java dev. / Product Lead
JRebel
Java… Do you speak it!?
Java… Do you speak it!?
The Master Plan
Bytecode 101
Examples
THE INTRO
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
+
? = 1 + 2
TAXONOMY
Bytecode
One-byte instructions
256 possible opcodes
200+ in use
Bytecode
One-byte instructions
256 possible opcodes
200+ in use
TYPE OPERATION
<TYPE> ::= b, s, c, i, l, f, d, a
TYPE OPERATION
<TYPE> ::= b, s, c, i, l, f, d, a
Operations with constant values (ldc, iconst_1)
TYPE OPERATION
<TYPE> ::= b, s, c, i, l, f, d, a
Operations with 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 (cmpg, cmpl, ifne, ifeq)
Conversions (l2d, i2l)
TYPE OPERATION
Bytecode Taxonomy
Stack
Manipulation
Bytecode Taxonomy
Stack
Manipulation
Flow
Control
Bytecode Taxonomy
Stack
Manipulation
Flow
Control
Object
Model
Bytecode Taxonomy
Stack
Manipulation
Flow
Control
Arithmetics Object
Model
Arithmetics
Bytecode Taxonomy
Stack
Manipulation
Flow
Control
Object
Model
monitorenter
monitorexit
TOOLING
javap -c -verbose Clazz
HELLO, WORLD!
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\classes>javap Hello -c
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\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 class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\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
the default constructor
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\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
push this to stack
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\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
invoke <init> on this
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\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 class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\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
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\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
get static field
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\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
load string to the stack
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\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
invoke method with parameter
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\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
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\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
What’s #1,#2, etc ?
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\classes>javap Hello -c -verbose
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\classes>javap Hello -c -verbose
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\classes>javap Hello -c -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;
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\classes>javap Hello -c -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;
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\classes>javap Hello -c -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;
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\classes>javap Hello -c -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;
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
C:\work\geecon\classes>javap Hello -c -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;
public class Hello {
public static void main(String[] args) {
System.out.println ( “Hello, World!” );
}
}
STACK
MACHINE
Stack Machine
Stack Machine
JVM is a stack-based machine
Stack Machine
JVM is a stack-based machine
Each thread has a stack
Stack Machine
JVM is a stack-based machine
Each thread has a stack
Stack stores frames
Stack Machine
JVM is a stack-based machine
Each thread has a stack
Stack stores frames
Frame is created on method
invocation
Stack Machine
JVM is a stack-based machine
Each thread has a stack
Stack stores frames
Frame is created on method
invocation
Frame consists of: Operand stack
Array of local variables
Operand stack
Local variables
2 0 1 N …
Constant
Pool
#1
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 class Get {
String name;
public String getName() {
return name;
}
}
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 class Get {
String name;
public String getName() {
return name;
}
}
aload_0 getfield 00 02 areturn
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;
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
STACK
JUGGLING
A B
dup
pop
swap
dup_x1
dup2_x1
A
B
dup
pop
swap
dup_x1
dup2_x1
A
dup
pop
swap
dup_x1
dup2_x1
A B
dup
pop
swap
dup_x1
dup2_x1
A B
dup
pop
swap
dup_x1
dup2_x1
A B
B
dup
pop
swap
dup_x1
dup2_x1
A B
B B A
How do you
swap doubles?
dup2_x2
dup2_x2
dconst_0 0.0
dup2_x2
dconst_0
dconst_1 1.0
0.0
dup2_x2
dconst_0
dconst_1
swap
1.0
0.0
dup2_x2
dconst_0
dconst_1
swap
1.0
0.0
not allowed!
dup2_x2
dconst_0
dconst_1
swap2
1.0
0.0
dup2_x2
dconst_0
dconst_1
swap2
1.0
0.0
doesn’t
exist
dup2_x2
dconst_0
dconst_1
dup2_x2
1.0
0.0
1.0
dup2_x2
dconst_0
dconst_1
dup2_x2
pop2
0.0
1.0
dup2_x2
dconst_0
dconst_1
dup2_x2
pop2
0.0
1.0
profit!
LOCAL
VARIABLES
Local Variables
public int calculate(int value) {
return value + 42;
}
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 value) {
return value + 42;
}
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 value) {
return value + 42;
}
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 value) {
return value + 42;
}
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 value) {
return value + 42;
}
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
public int calculate(int value) {
return value + 42;
}
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
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
ldc "Hello"
astore_0
iconst_1
astore_1
aload_0
depth value var value
Local Variables
"Hello" 0
1
2
3
4
0
1
2
3
4
Stack
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
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
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"
Stack Local
Variables
Table
store
load
OBJECTS
new
<init>
<clinit> Instance initialization method
Class and interface
initialization method
Object Initialization
0xBB
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
public class Initializer {
static int a;
static int b;
static { a = 1; }
static { b = 2; }
}
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>
public class Initializer {
static int a;
static int b;
static { a = 1; }
static { b = 2; }
}
Object Initialization: new
public class Initializer {
Object o;
public Initializer() {
o = new Object();
}
}
Object Initialization: new
public Initializer();
Code:
public class Initializer {
Object o;
public Initializer() {
o = new Object();
}
}
Object Initialization: new
public Initializer();
Code:
0: aload_0
public class Initializer {
Object o;
public Initializer() {
o = new Object();
}
}
Object Initialization: new
public Initializer();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
public class Initializer {
Object o;
public Initializer() {
o = new Object();
}
}
Object Initialization: new
public Initializer();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
public class Initializer {
Object o;
public Initializer() {
o = new Object();
}
}
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
public class Initializer {
Object o;
public Initializer() {
o = new Object();
}
}
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;
public class Initializer {
Object o;
public Initializer() {
o = new Object();
}
}
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
public class Initializer {
Object o;
public Initializer() {
o = new Object();
}
}
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
public class Initializer {
Object o;
public Initializer() {
o = new Object();
}
}
Object Initialization: {}
public class Initializer {
int a;
int b;
int c;
{ a = 1; }
public Initializer(int b) {
this.b = b;
}
{ c = 2; }
}
Object Initialization: {}
public class Initializer {
int a;
int b;
int c;
{ a = 1; }
public Initializer(int b) {
this.b = b;
}
{ c = 2; }
}
Object Initialization: {}
public class Initializer {
int a;
int b;
int c;
{ a = 1; }
public Initializer(int b) {
this.b = b;
}
{ c = 2; }
}
Object Initialization: {}
public class Initializer {
int a;
int b;
int c;
{ a = 1; }
public Initializer(int b) {
this.b = b;
}
{ c = 2; }
}
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
public class Initializer {
int a;
int b;
int c;
{ a = 1; }
public Initializer(int b) {
this.b = b;
}
{ c = 2; }
}
There’s no initializer
METHOD INVOCATION
&
PARAMETER PASSING
METHOD
INVOCATION
Java Method Invocation
Java Method Invocation
invokestatic
invokespecial
invokevirtual
invokeinterface
invokedynamic
Java Method Invocation
invokestatic
invokespecial
invokevirtual
invokeinterface
invokedynamic Integer.valueOf(“42”)
Java Method Invocation
invokestatic
invokespecial
invokevirtual
invokeinterface
invokedynamic
<init>
private void foo();
super.method();
Java Method Invocation
invokestatic
invokespecial
invokevirtual
invokeinterface
invokedynamic
class A A/method1
A/method2
Java Method Invocation
invokestatic
invokespecial
invokevirtual
invokeinterface
invokedynamic
class A
class B
A/method1
A/method2
Java Method Invocation
invokestatic
invokespecial
invokevirtual
invokeinterface
invokedynamic
class A
class B
A/method1
A/method2
A/method1
B/method2
B/method3
Java Method Invocation
invokestatic
invokespecial
invokevirtual
invokeinterface
invokedynamic
class A
class B impl X
A/method1
A/method2
A/method1
B/method2
B/method3
X/methodX
Java Method Invocation
invokestatic
invokespecial
invokevirtual
invokeinterface
invokedynamic
class A
class B impl X
A/method1
A/method2
A/method1
B/method2
B/method3
X/methodX class D impl X
D/method1
X/methodX
Java Method Invocation
invokestatic
invokespecial
invokevirtual
invokeinterface
invokedynamic
class A
class B impl X
A/method1
A/method2
A/method1
B/method2
B/method3
X/methodX class D impl X
D/method1
X/methodX
Java Method Invocation
invokestatic
invokespecial
invokevirtual
invokeinterface
invokedynamic
Efficient Implementation of Java Interfaces:
Invokeinterface Considered Harmless, Bowen
Alpern, Anthony Cocchi, Stephen Fink, David
Grove, and Derek Lieber, OOPSLA’01
Method Invocation
obj.method(param1, param2);
Method Invocation
obj.method(param1, param2);
push obj
push param1
push param2
call method
Method Invocation
obj.method(param1, param2); obj
push obj
push param1
push param2
call method
Method Invocation
obj.method(param1, param2);
obj
param1 push obj
push param1
push param2
call method
Method Invocation
obj.method(param1, param2);
obj
param1
param2 push obj
push param1
push param2
call method
Method Invocation
obj.method(param1, param2); obj?
push obj
push param1
push param2
call method
INNER
CLASSES
Inner Classes
public class Car {
class Engine {
public void start() {
move();
}
}
private void move() {
}
}
Inner Classes
class Car$Engine extends j.l.Object{
final Car this$0;
Car$Engine(Car);
public void start();
Code:
0: aload_0
1: getfield #1; //Field this$0:LCar;
4: invokestatic #3; // Car.access$000:(LCar;)V
7: return
}
Inner Classes
public class Car extends j.l.Object{
public Car();
private void move();
static void access$000(Car);
Code:
0: aload_0
1: invokespecial #1; // move: ()V;
4: return
}
class Car$Engine extends j.l.Object{
final Car this$0;
Car$Engine(Car);
public void start();
Code:
0: aload_0
1: getfield #1; //Field this$0:LCar;
4: invokestatic #3; // Car.access$000:(LCar;)V
7: return
}
Inner Classes
public class Car extends j.l.Object{
public Car();
private void move();
static void access$000(Car);
Code:
0: aload_0
1: invokespecial #1; // move: ()V;
4: return
}
class Car$Engine extends j.l.Object{
final Car this$0;
Car$Engine(Car);
public void start();
Code:
0: aload_0
1: getfield #1; //Field this$0:LCar;
4: invokestatic #3; // Car.access$000:(LCar;)V
7: return
}
“HOW DO THEY DO THAT?”
object Singleton {
def test={}
}
object Singleton {
def test={}
}
$> scalac Singleton.scala
Singleton.class Singleton$.class
public final class Singleton extends java.lang.Object {
public static final void test();
Code:
0: getstatic #11; //Field Singleton$.MODULE$:LSingleton$;
3: invokevirtual #13; //Method Singleton$.test:()V
6: return
}
public final class Singleton extends java.lang.Object {
public static final void test();
Code:
0: getstatic #11; //Field Singleton$.MODULE$:LSingleton$;
3: invokevirtual #13; //Method Singleton$.test:()V
6: return
}
public final class Singleton extends java.lang.Object {
public static final void test();
Code:
0: getstatic #11; //Field Singleton$.MODULE$:LSingleton$;
3: invokevirtual #13; //Method Singleton$.test:()V
6: return
}
public final class Singleton extends java.lang.Object {
public static final void test();
Code:
0: getstatic #11; //Field Singleton$.MODULE$:LSingleton$;
3: invokevirtual #13; //Method Singleton$.test:()V
6: return
}
public final class Singleton$ extends java.lang.Object implements
scala.ScalaObject {
public static final Singleton$ MODULE$;
public static {};
Code:
0: new #9; //class Singleton$
3: invokespecial #12; //Method "<init>":()V
6: return
public void test();
private Singleton$();
}
public final class Singleton extends java.lang.Object {
public static final void test();
Code:
0: getstatic #11; //Field Singleton$.MODULE$:LSingleton$;
3: invokevirtual #13; //Method Singleton$.test:()V
6: return
}
public final class Singleton$ extends java.lang.Object implements
scala.ScalaObject {
public static final Singleton$ MODULE$;
public static {};
Code:
0: new #9; //class Singleton$
3: invokespecial #12; //Method "<init>":()V
6: return
public void test();
private Singleton$();
}
public final class Singleton extends java.lang.Object {
public static final void test();
Code:
0: getstatic #11; //Field Singleton$.MODULE$:LSingleton$;
3: invokevirtual #13; //Method Singleton$.test:()V
6: return
}
public final class Singleton$ extends java.lang.Object implements
scala.ScalaObject {
public static final Singleton$ MODULE$;
public static {};
Code:
0: new #9; //class Singleton$
3: invokespecial #12; //Method "<init>":()V
6: return
public void test();
private Singleton$();
}
public final class Singleton extends java.lang.Object {
public static final void test();
Code:
0: getstatic #11; //Field Singleton$.MODULE$:LSingleton$;
3: invokevirtual #13; //Method Singleton$.test:()V
6: return
}
public final class Singleton$ extends java.lang.Object implements
scala.ScalaObject {
public static final Singleton$ MODULE$;
public static {};
public void test();
private Singleton$();
Code:
0: aload_0
1: invokespecial #17; //Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #19; //Field MODULE$:LSingleton$;
8: return
object Singleton {
def test={}
}
object Singleton {
def test={}
}
public class Singleton {
public void test(){
Singleton$.MODULE$.test();
}
}
object Singleton {
def test={}
}
public class Singleton {
public void test(){
Singleton$.MODULE$.test();
}
}
public final class Singleton$
implements scala.ScalaObject {
public static final Singleton$ MODULE$;
static { new Singleton$(); }
private Singleton$(){
MODULE$ = this;
}
public void test() {
}
}
CRASH!
BOOM!
BANG!
Javassist
Bytecode manipulation made easy
Source-level and bytecode-level API
Uses the vocabulary of Java language
On-the-fly compilation of the injected code
http://www.jboss.org/javassist
for(int i = 0; i < 100; i++){
int a = 0;
try {
while (true) {
a++;
foo(a);
if(a > 1) break;
}
} catch (Exception e) {
}
}
Javassist
for(int i = 0; i < 100; i++){
int a = 0;
try {
while (true) {
a++;
foo(a);
if(a > 1) break;
}
} catch (Exception e) {
}
}”);
method.setBody(“
CtMethod method = …
Exception in thread "main" java.lang.VerifyError:
(class: zt/javassist/My, method: test signature:
()V) Inconsistent stack height 0 != 1
-Xverify:all
public void test();
Code:
Stack=2, Locals=4, Args_size=1
0: iconst_0
1: istore_1
2: iload_1
3: bipush 100
5: if_icmpge 42
8: iconst_0
9: istore_2
10: goto 29
13: iinc 2, 1
16: aload_0
17: iload_2
18: invokevirtual #23; //Method zt/javassist/My.foo:(I)V
21: iload_2
22: iconst_1
23: if_icmple 29
26: goto 32
29: goto 13
32: astore_3
33: goto 36
36: iinc 1, 1
39: goto 2
42: return
Exception table:
from to target type
10 32 32 Class java/lang/Exception
public void test();
Code:
Stack=2, Locals=4, Args_size=1
0: iconst_0
1: istore_1
2: iload_1
3: bipush 100
5: if_icmpge 42
8: iconst_0
9: istore_2
10: goto 29
13: iinc 2, 1
16: aload_0
17: iload_2
18: invokevirtual #23; //Method zt/javassist/My.foo:(I)V
21: iload_2
22: iconst_1
23: if_icmple 29
26: goto 32
29: goto 13
32: astore_3
33: goto 36
36: iinc 1, 1
39: goto 2
42: return
Exception table:
from to target type
10 32 32 Class java/lang/Exception
No local
variables table
public void test();
Code:
Stack=2, Locals=4, Args_size=1
0: iconst_0
1: istore_1
2: iload_1
3: bipush 100
5: if_icmpge 42
8: iconst_0
9: istore_2
10: goto 29
13: iinc 2, 1
16: aload_0
17: iload_2
18: invokevirtual #23; //Method zt/javassist/My.foo:(I)V
21: iload_2
22: iconst_1
23: if_icmple 29
26: goto 32
29: goto 13
32: astore_3
33: goto 36
36: iinc 1, 1
39: goto 2
42: return
Exception table:
from to target type
10 32 32 Class java/lang/Exception
No local
variables table
Bytecode is fun!
Know your platform!
Maybe, you can build your own language?
You may need to read bytecode someday.