java bytecode for discriminating developers - geecon 2011
TRANSCRIPT
Java Bytecode for Discriminating Developers
Anton Arhipov
whoami
http://arhipov.blogspot.com@antonarhipov
@javarebel
Anton ArhipovJava dev. / Product Lead
JRebel
Who-are-you?
The Master Plan
80%: Bytecode 101
20%: Examples
THE INTRO
1 + 2
1 + 21 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 1PUSH 2
21
1 2+
1 + 2
1 2 + PUSH 1PUSH 2ADD
3
1 2+
1 + 2
1 2 + ICONST_1ICONST_2IADD
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
FlowControl
Bytecode Taxonomy
Stack Manipulation
FlowControl
Object Model
Bytecode Taxonomy
Stack Manipulation
FlowControl
ArithmeticsObject Model
Bytecode Taxonomy
Stack Manipulation
FlowControl
ArithmeticsObject Model
monitorentermonitorexit
TOOLING
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
HELLO WORLD!
C:\work\geecon\classes>javap Hello -c
C:\work\geecon\classes>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
C:\work\geecon\classes>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
the default constructor
C:\work\geecon\classes>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
push this to stack
C:\work\geecon\classes>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
invoke <init> on this
C:\work\geecon\classes>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
C:\work\geecon\classes>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
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\geecon\classes>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
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
C:\work\geecon\classes>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
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:\work\geecon\classes>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
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:\work\geecon\classes>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
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\geecon\classes>javap Hello -cCompiled from "Hello.java"public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
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:\work\geecon\classes>javap Hello -c -verbose
C:\work\geecon\classes>javap Hello -c -verbose
C:\work\geecon\classes>javap Hello -c -verboseCompiled 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>":()Vconst #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;)Vconst #5 = class #26; // Helloconst #6 = class #27; // java/lang/Objectconst #7 = Asciz <init>;const #8 = Asciz ()V;
C:\work\geecon\classes>javap Hello -c -verboseCompiled 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>":()Vconst #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;)Vconst #5 = class #26; // Helloconst #6 = class #27; // java/lang/Objectconst #7 = Asciz <init>;const #8 = Asciz ()V;
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;
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;
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;
C:\work\geecon\classes>javap Hello -c -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
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
The Frame
Operand stack
Local variables
31 2 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: areturnLocalVariableTable: 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: areturnLocalVariableTable: 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: areturnLocalVariableTable: 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: areturnLocalVariableTable: Start Length Slot Name Signature 0 5 0 this LGet;
STACK CRUNCHING
AB
duppopswapdup_x1dup2_x2
A
B
duppopswapdup_x1dup2_x2
A
duppopswapdup_x1dup2_x2
AB
duppopswapdup_x1dup2_x2
AB
duppopswapdup_x1dup2_x2
AB
B
duppopswapdup_x1dup2_x2
AB
BBA
dup2_x2
How do you swap doubles?
dup2_x2
dup2_x2
dconst_00.0
dup2_x2
dconst_0dconst_1 1.0
0.0
dup2_x2
dconst_0dconst_1swap
1.0
0.0
dup2_x2
dconst_0dconst_1swap
1.0
0.0
not allowed!
dup2_x2
dconst_0dconst_1swap2
1.0
0.0
dup2_x2
dconst_0dconst_1swap2
1.0
0.0
doesn’texist
dup2_x2
dconst_0dconst_1dup2_x2
1.0
0.0
1.0
dup2_x2
dconst_0dconst_1dup2_x2pop2
0.0
1.0
dup2_x2
dconst_0dconst_1dup2_x2pop2
0.0
1.0
profit!
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
numbered
from 0
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
instance methodshave this at 0
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_0iconst_1astore_1aload_0
depth value
Stack
var value
Local Variables
0
1
2
3
4
0
1
2
3
4
ldc "Hello"astore_0iconst_1astore_1aload_0
depth value
Stack
var value
Local Variables
"Hello"0
1
2
3
4
0
1
2
3
4
ldc "Hello"astore_0iconst_1astore_1aload_0
depth valuevar value
Local Variables
"Hello"0
1
2
3
4
0
1
2
3
4
Stack
ldc "Hello"astore_0iconst_1astore_1aload_0
depth value
Stack
var value
Local Variables
"Hello"0
1
2
3
4
0
1
2
3
4
1
ldc "Hello"astore_0iconst_1astore_1aload_0
depth value
Stack
var value
Local Variables
"Hello"0
1
2
3
4
0
1
2
3
4
1
ldc "Hello"astore_0iconst_1astore_1aload_0
depth value
Stack
var value
Local Variables
"Hello"0
1
2
3
4
0
1
2
3
4
1
"Hello"
StackLocal
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
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
Object Initialization: new
public Initializer(); Code:
Object Initialization: new
public Initializer(); Code: 0: aload_0
Object Initialization: new
public Initializer(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V
Object Initialization: new
public Initializer(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: aload_0
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
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;
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
There’s no initializer
METHOD INVOCATION&
PARAMETER PASSING
Methods & Parameters
• 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
Methods & Parameters
• 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
Integer.valueOf(“42”)
Methods & Parameters
• 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
<init>
private void foo();
super.method();
Methods & Parameters
• 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
class AA/method1A/method2
Methods & Parameters
• 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
class A
class B
A/method1A/method2
Methods & Parameters
• 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
class A
class B
A/method1A/method2
A/method1B/method2B/method3
Methods & Parameters
• 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
class A
class B impl X
A/method1A/method2
A/method1B/method2B/method3X/methodX
Methods & Parameters
• 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
class A
class B impl X
A/method1A/method2
A/method1B/method2B/method3X/methodX class D impl X
D/method1X/methodX
Methods & Parameters
• 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
class A
class B impl X
A/method1A/method2
A/method1B/method2B/method3X/methodX class D impl X
D/method1X/methodX
Methods & Parameters
• 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 objpush param1push param2call method
Method Invocation
obj.method(param1, param2);
push objpush param1push param2call method
obj
Method Invocation
obj.method(param1, param2);
push objpush param1push param2call method
obj
param1
Method Invocation
obj.method(param1, param2);
push objpush param1push param2call method
obj
param1
param2
Method Invocation
obj.method(param1, param2);
push objpush param1push param2call method
obj?
Method Invocation
this.add(1, 2);
0: aload_01: iconst_12: iconst_23: invokevirtual #2; //Method add:(II)I
INNER CLASSES
Inner Classes
Inner Classes
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() { }}
class Groovy { }
class Groovy { }
$> groovyc Groovy.groovy$> javap –c –p Groovy
class Groovy { }
$> groovyc Groovy.groovy$> javap –c –p Groovypublic class Test extends java.lang.Object implements groovy.lang.GroovyObject{ private static org.codehaus.groovy.reflection.ClassInfo $staticClassInfo; private transient groovy.lang.MetaClass metaClass; public static java.lang.Long __timeStamp; public static java.lang.Long __timeStamp__239_neverHappen1304807931117; private static java.lang.ref.SoftReference $callSiteArray; private static java.lang.Class $class$groovy$lang$MetaClass; private static java.lang.Class $class$Test; private static java.lang.Class $class$java$lang$String; public java.lang.Object this$dist$invoke$2(java.lang.String, java.lang.Object); public void this$dist$set$2(java.lang.String, java.lang.Object); public java.lang.Object this$dist$get$2(java.lang.String); protected groovy.lang.MetaClass $getStaticMetaClass(); public groovy.lang.MetaClass getMetaClass(); public void setMetaClass(groovy.lang.MetaClass); public java.lang.Object invokeMethod(java.lang.String, java.lang.Object); public java.lang.Object getProperty(java.lang.String); public void setProperty(java.lang.String, java.lang.Object);
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) { }}
for(int i = 0; i < 100; i++){ int a = 0; try { while (true) { a++; foo(a); if(a > 1) break; } } catch (Exception e) { }}
for(int i = 0; i < 100; i++){ int a = 0; try { while (true) { a++; foo(a); if(a > 1) break; } } catch (Exception e) { }}
for(int i = 0; i < 100; i++){ int a = 0; try { while (true) { a++; foo(a); if(a > 1) break; } } catch (Exception e) { }}
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 = …
-noverify
## A fatal error has been detected by the Java Runtime Environment:## EXCEPTION_ACCESS_VIOLATION (0xc0000005) at # pc=0x01adff06, pid=7732, tid=868## JRE version: 6.0_21-b07# Java VM: Java HotSpot(TM) Client VM (17.0-b17 mixed mode, # sharing windows-x86 )# Problematic frame:# j zt.javassist.My.test()V+20## An error report file with more information is saved as:# C:\work\puzzlers\hs_err_pid7732.log## If you would like to submit a bug report, please visit:# http://java.sun.com/webapps/bugreport/crash.jsp#
-noverify
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
Q/A