mastering java bytecode - jax.de 2012
DESCRIPTION
TRANSCRIPT
Mastering Java Bytecode
Anton Arhipov | ZeroTurnaround
whoami
• Anton Arhipov• Java Dev / Product Lead• ZeroTurnaround, JRebel
• @antonarhipov @javarebel
Today – Java Core
• Mastering Java Bytecode
• The Future of Java on Multi-Core, Lambdas, Spliterators and Methods
• OpenJDK JVM Internals
• Invokedynamic Deep Dive
Why Bytecode?
• Know your platform!• Create your own compiler?• Programming model (AOP, ORM)• Awesome tools (JRebel )
• … just bored?
THE INTRO
1 + 2
1 + 2
1 2 +
1 + 2
1 2 +
1 + 2
1 2 + PUSH 1 1
1 + 2
1 2 + PUSH 1PUSH 2
21
1 + 2
1 2 + PUSH 1PUSH 2ADD
3
1 + 2
1 2 + ICONST_1ICONST_2IADD
3
? = 1 + 2
TAXONOMY
Bytecode
• One-byte instructions• 256 possible opcodes• 200+ in use
TYPE OPERATION
• <TYPE> ::= b, s, c, i, l, f, d, a
OPERATIONTYPE
• <TYPE> ::= b, s, c, i, l, f, d, a• constant values (ldc, iconst_1)
OPERATIONTYPE
• <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 (cmpg, cmpl, ifne, ifeq)• Conversions (l2d, i2l)
OPERATIONTYPE
Bytecode Taxonomy
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;
MODEL OF COMPUTATION
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
20 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: 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_x1
A
B
duppopswapdup_x1dup2_x1
A
duppopswapdup_x1dup2_x1
AB
duppopswapdup_x1dup2_x1
AB
duppopswapdup_x1dup2_x1
AB
B
duppopswapdup_x1dup2_x1
AB
BBA
dup2_x2
How do you swap doubles?
dup2_x2
dup2_x2dconst_0
0.0
dup2_x2dconst_0dconst_1 1.0
0.0
dup2_x2dconst_0dconst_1swap
1.0
0.0
dup2_x2dconst_0dconst_1swap
1.0
0.0
not allowed!
dup2_x2dconst_0dconst_1swap2
1.0
0.0
dup2_x2dconst_0dconst_1swap2
1.0
0.0
doesn’texist
dup2_x2dconst_0dconst_1dup2_x2
1.0
0.0
1.0
dup2_x2dconst_0dconst_1dup2_x2pop2
0.0
1.0
dup2_x2dconst_0dconst_1dup2_x2pop2
0.0
1.0
profit!
LOCAL VARIABLES
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
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
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
The table maps
numbers to names
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
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
invokeXXX
• invokestatic• invokespecial• invokevirtual• invokeinterface• invokedynamic
invokestatic
• invokestatic• invokespecial• invokevirtual• invokeinterface• invokedynamic
Integer.valueOf(“42”)
invokespecial
• invokestatic• invokespecial• invokevirtual• invokeinterface• invokedynamic
<init>
private void foo();
super.method();
invokevirtual
• invokestatic• invokespecial• invokevirtual• invokeinterface• invokedynamic
class AA/method1A/method2
invokevirtual
• invokestatic• invokespecial• invokevirtual• invokeinterface• invokedynamic
class A
class B
A/method1A/method2
invokevirtual
• invokestatic• invokespecial• invokevirtual• invokeinterface• invokedynamic
class A
class B
A/method1A/method2
A/method1B/method2B/method3
invokeinterface
• invokestatic• invokespecial• invokevirtual• invokeinterface• invokedynamic
class A
class B impl X
A/method1A/method2
A/method1B/method2B/method3X/methodX
invokeinterface
• invokestatic• invokespecial• invokevirtual• invokeinterface• invokedynamic
class A
class B impl X
A/method1A/method2
A/method1B/method2B/method3X/methodX
D impl XD/method1X/methodX
invokeinterface
• invokestatic• invokespecial• invokevirtual• invokeinterface• invokedynamic
class A
class B impl X
A/method1A/method2
A/method1B/method2B/method3X/methodX
D impl XD/method1X/methodX
invokeinterface
• 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
D impl XD/method1X/methodX
Method Invocation
Method Invocation
obj.method(param1, param2);
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 Classespublic 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 Classespublic 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);
OBJECTWEB ASM
SLIDESGOTO IDESLIDESIDE: DEMO
@antonarhipov