in practice source code source code javac scalac groovyc jrubyc - - PowerPoint PPT Presentation

in practice source code source code javac scalac groovyc
SMART_READER_LITE
LIVE PREVIEW

in practice source code source code javac scalac groovyc jrubyc - - PowerPoint PPT Presentation

Java byte code in practice source code source code javac scalac groovyc jrubyc 0xCAFEBABE byte code source code javac scalac groovyc jrubyc 0xCAFEBABE byte code class loader interpreter JIT compiler JVM source code javac


slide-1
SLIDE 1

Java byte code in practice

slide-2
SLIDE 2

source code

slide-3
SLIDE 3

0xCAFEBABE source code byte code javac scalac groovyc jrubyc

slide-4
SLIDE 4

0xCAFEBABE source code byte code JVM javac scalac groovyc jrubyc JIT compiler interpreter class loader

slide-5
SLIDE 5

0xCAFEBABE source code byte code JVM javac scalac groovyc jrubyc JIT compiler interpreter class loader creates

slide-6
SLIDE 6

0xCAFEBABE source code byte code JVM javac scalac groovyc jrubyc JIT compiler interpreter class loader creates reads

slide-7
SLIDE 7

0xCAFEBABE source code byte code JVM javac scalac groovyc jrubyc JIT compiler interpreter class loader creates reads runs

slide-8
SLIDE 8

source code byte code void foo() { }

slide-9
SLIDE 9

source code byte code void foo() { } RETURN

slide-10
SLIDE 10

source code byte code void foo() { } RETURN return;

slide-11
SLIDE 11

source code byte code void foo() { } return; 0xB1

slide-12
SLIDE 12

source code byte code int foo() { return 1 + 2; }

slide-13
SLIDE 13

source code byte code int foo() { return 1 + 2; } ICONST_1 ICONST_2 IADD

slide-14
SLIDE 14

source code byte code int foo() { return 1 + 2; } ICONST_1 ICONST_2 IADD

  • perand stack
slide-15
SLIDE 15

source code byte code int foo() { return 1 + 2; } ICONST_1 ICONST_2 IADD

  • perand stack

1

slide-16
SLIDE 16

source code byte code int foo() { return 1 + 2; } ICONST_1 ICONST_2 IADD

  • perand stack

2 1

slide-17
SLIDE 17

source code byte code int foo() { return 1 + 2; } ICONST_1 ICONST_2 IADD

  • perand stack

3

slide-18
SLIDE 18

source code byte code int foo() { return 1 + 2; } ICONST_1 ICONST_2 IADD

  • perand stack

3 IRETURN

slide-19
SLIDE 19

source code byte code int foo() { return 1 + 2; } ICONST_1 ICONST_2 IADD

  • perand stack

IRETURN

slide-20
SLIDE 20

source code byte code int foo() { return 1 + 2; }

  • perand stack

0x04 0x05 0x60 0xAC

slide-21
SLIDE 21

source code byte code int foo() { return 11 + 2; }

  • perand stack
slide-22
SLIDE 22

source code byte code BIPUSH int foo() { return 11 + 2; }

  • perand stack

11

slide-23
SLIDE 23

source code byte code BIPUSH int foo() { return 11 + 2; }

  • perand stack

11 11

slide-24
SLIDE 24

source code byte code ICONST_2 IADD IRETURN BIPUSH int foo() { return 11 + 2; }

  • perand stack

11 11

slide-25
SLIDE 25

source code byte code ICONST_2 IADD IRETURN BIPUSH int foo() { return 11 + 2; }

  • perand stack

2 11 11

slide-26
SLIDE 26

source code byte code ICONST_2 IADD IRETURN BIPUSH int foo() { return 11 + 2; }

  • perand stack

13 11

slide-27
SLIDE 27

source code byte code ICONST_2 IADD IRETURN BIPUSH int foo() { return 11 + 2; }

  • perand stack

11

slide-28
SLIDE 28

source code byte code ICONST_2 IADD IRETURN int foo() { return 11 + 2; }

  • perand stack

0x10 11

slide-29
SLIDE 29

source code byte code ICONST_2 IADD IRETURN int foo() { return 11 + 2; }

  • perand stack

0x10 0x0B

slide-30
SLIDE 30

source code byte code int foo() { return 11 + 2; }

  • perand stack

0x05 0x60 0xAC 0x10 0x0B

slide-31
SLIDE 31

source code byte code int foo(int i) { return i + 1; }

  • perand stack
slide-32
SLIDE 32

source code byte code int foo(int i) { return i + 1; } ILOAD_1

  • perand stack
slide-33
SLIDE 33

source code byte code int foo(int i) { return i + 1; } ILOAD_1

  • perand stack

local variable array 1 : i 0 : this

slide-34
SLIDE 34

source code byte code int foo(int i) { return i + 1; } ILOAD_1

  • perand stack

local variable array 1 : i 0 : this i

slide-35
SLIDE 35

source code byte code int foo(int i) { return i + 1; } ILOAD_1 ICONST_1 IADD IRETURN

  • perand stack

local variable array 1 : i 0 : this i

slide-36
SLIDE 36

source code byte code int foo(int i) { return i + 1; } ILOAD_1 ICONST_1 IADD IRETURN

  • perand stack

local variable array 1 : i 0 : this 1 i

slide-37
SLIDE 37

source code byte code int foo(int i) { return i + 1; } ILOAD_1 ICONST_1 IADD IRETURN

  • perand stack

local variable array 1 : i 0 : this i + 1

slide-38
SLIDE 38

source code byte code int foo(int i) { return i + 1; } ILOAD_1 ICONST_1 IADD IRETURN

  • perand stack

local variable array 1 : i 0 : this

slide-39
SLIDE 39

source code byte code int foo(int i) { return i + 1; }

  • perand stack

local variable array 1 : i 0 : this 0x1B 0x04 0x60 0xAC

slide-40
SLIDE 40

source code byte code long foo(long i) { return i + 1L; }

slide-41
SLIDE 41

source code byte code long foo(long i) { return i + 1L; } LLOAD_1 LCONST_1 LADD LRETURN

slide-42
SLIDE 42

source code byte code long foo(long i) { return i + 1L; } LLOAD_1 LCONST_1 LADD LRETURN local variable array 2 : i (cn.) 1 : i 0 : this

slide-43
SLIDE 43

source code byte code long foo(long i) { return i + 1L; } LLOAD_1 LCONST_1 LADD LRETURN

  • perand stack

local variable array 2 : i (cn.) 1 : i 0 : this i (cn.) i

slide-44
SLIDE 44

source code byte code long foo(long i) { return i + 1L; } LLOAD_1 LCONST_1 LADD LRETURN

  • perand stack

local variable array 2 : i (cn.) 1 : i 0 : this i (cn.) i 1L 1L (cn.)

slide-45
SLIDE 45

source code byte code long foo(long i) { return i + 1L; } LLOAD_1 LCONST_1 LADD LRETURN

  • perand stack

local variable array 2 : i (cn.) 1 : i 0 : this i + 1L i + 1L (cn.)

slide-46
SLIDE 46

source code byte code long foo(long i) { return i + 1L; } LLOAD_1 LCONST_1 LADD LRETURN

  • perand stack

local variable array 2 : i (cn.) 1 : i 0 : this

slide-47
SLIDE 47

source code byte code long foo(long i) { return i + 1L; }

  • perand stack

local variable array 2 : i (cn.) 1 : i 0 : this 0x1F 0x0A 0x61 0xAD

slide-48
SLIDE 48

source code byte code short foo(short i) { return (short) (i + 1); }

  • perand stack

local variable array 1 : i 0 : this

slide-49
SLIDE 49

source code byte code short foo(short i) { return (short) (i + 1); } ILOAD_1 ICONST_1 IADD

  • perand stack

local variable array 1 : i 0 : this

slide-50
SLIDE 50

source code byte code short foo(short i) { return (short) (i + 1); } ILOAD_1 ICONST_1 IADD

  • perand stack

local variable array 1 : i 0 : this i

slide-51
SLIDE 51

source code byte code short foo(short i) { return (short) (i + 1); } ILOAD_1 ICONST_1 IADD

  • perand stack

local variable array 1 : i 0 : this 1 i

slide-52
SLIDE 52

source code byte code short foo(short i) { return (short) (i + 1); } ILOAD_1 ICONST_1 IADD

  • perand stack

local variable array 1 : i 0 : this i + 1

slide-53
SLIDE 53

source code byte code short foo(short i) { return (short) (i + 1); } ILOAD_1 ICONST_1 IADD I2S

  • perand stack

local variable array 1 : i 0 : this i + 1

slide-54
SLIDE 54

source code byte code short foo(short i) { return (short) (i + 1); } ILOAD_1 ICONST_1 IADD I2S

  • perand stack

local variable array 1 : i 0 : this i + 1

slide-55
SLIDE 55

source code byte code short foo(short i) { return (short) (i + 1); } ILOAD_1 ICONST_1 IADD I2S IRETURN

  • perand stack

local variable array 1 : i 0 : this i + 1

slide-56
SLIDE 56

source code byte code short foo(short i) { return (short) (i + 1); } ILOAD_1 ICONST_1 IADD I2S IRETURN

  • perand stack

local variable array 1 : i 0 : this

slide-57
SLIDE 57

source code byte code short foo(short i) { return (short) (i + 1); }

  • perand stack

local variable array 1 : i 0 : this 0x1B 0x04 0x60 0x93 0xAC

slide-58
SLIDE 58

source code byte code void foo() { return; } RETURN

slide-59
SLIDE 59

source code byte code void foo() { return; } RETURN

slide-60
SLIDE 60

source code byte code void foo() { return; } RETURN

slide-61
SLIDE 61

source code byte code void foo() { return; } RETURN 0x0000 foo ()V

slide-62
SLIDE 62

source code byte code void foo() { return; } RETURN 0x0000 foo ()V 1

  • perand stack

///////////////// local variable array 0 : this

slide-63
SLIDE 63

source code byte code void foo() { return; } RETURN 0x0000 foo ()V 1

  • perand stack

///////////////// local variable array 0 : this

slide-64
SLIDE 64

source code byte code pkg/Bar.class void foo() { return; } RETURN package pkg; class Bar { } 0x0000 foo ()V 1

  • perand stack

///////////////// local variable array 0 : this

slide-65
SLIDE 65

source code byte code pkg/Bar.class void foo() { return; } RETURN package pkg; class Bar { } constant pool (i.a. UTF-8) 0x0000 foo ()V 1

  • perand stack

///////////////// local variable array 0 : this

slide-66
SLIDE 66

source code byte code pkg/Bar.class void foo() { return; } RETURN package pkg; class Bar { } constant pool (i.a. UTF-8) 0x0000: foo 0x0001: ()V 0x0002: pkg/Bar 0x0000 foo ()V 1

  • perand stack

///////////////// local variable array 0 : this

slide-67
SLIDE 67

source code byte code pkg/Bar.class void foo() { return; } RETURN package pkg; class Bar { } constant pool (i.a. UTF-8) 0x0000: foo 0x0001: ()V 0x0002: pkg/Bar 0x0000 0x0000 ()V 1

  • perand stack

///////////////// local variable array 0 : this

slide-68
SLIDE 68

source code byte code pkg/Bar.class void foo() { return; } RETURN package pkg; class Bar { } constant pool (i.a. UTF-8) 0x0000: foo 0x0001: ()V 0x0002: pkg/Bar 0x0000 0x0000 0x0001 1

  • perand stack

///////////////// local variable array 0 : this

slide-69
SLIDE 69

source code byte code pkg/Bar.class void foo() { return; } package pkg; class Bar { } constant pool (i.a. UTF-8) 0x0000: foo 0x0001: ()V 0x0002: pkg/Bar 0xB1 0x0000 0x0000 0x0001 1

  • perand stack

///////////////// local variable array 0 : this

slide-70
SLIDE 70

source code byte code pkg/Bar.class void foo() { return; } package pkg; class Bar { } constant pool (i.a. UTF-8) 0x0000: foo 0x0001: ()V 0x0002: pkg/Bar 0xB1 0x0000 0x0000 0x0001 0x0000 1

  • perand stack

///////////////// local variable array 0 : this

slide-71
SLIDE 71

source code byte code pkg/Bar.class void foo() { return; } package pkg; class Bar { } constant pool (i.a. UTF-8) 0x0000: foo 0x0001: ()V 0x0002: pkg/Bar 0xB1 0x0000 0x0000 0x0001 0x0000 0x0001

  • perand stack

///////////////// local variable array 0 : this

slide-72
SLIDE 72

Java type JVM type (non-array) JVM descriptor stack slots boolean I Z 1 byte B 1 short S 1 char C 1 int I 1 long L J 2 float F F 1 double D D 2 void

  • V

java.lang.Object A Ljava/lang/Object; 1

slide-73
SLIDE 73

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } }

slide-74
SLIDE 74

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } ILOAD_1 ICONST_1 IADD

slide-75
SLIDE 75

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } ILOAD_1 ICONST_1 IADD INVOKEVIRTUAL

slide-76
SLIDE 76

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } ILOAD_1 ICONST_1 IADD INVOKEVIRTUAL pkg/Bar foo (I)I

slide-77
SLIDE 77

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } ILOAD_1 ICONST_1 IADD INVOKEVIRTUAL pkg/Bar foo (I)I local variable array 1 : i 0 : this

slide-78
SLIDE 78

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } ILOAD_1 ICONST_1 IADD INVOKEVIRTUAL pkg/Bar foo (I)I local variable array 1 : i 0 : this

slide-79
SLIDE 79

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } ILOAD_1 ICONST_1 IADD INVOKEVIRTUAL pkg/Bar foo (I)I ALOAD_0 local variable array 1 : i 0 : this

slide-80
SLIDE 80

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } ILOAD_1 ICONST_1 IADD INVOKEVIRTUAL pkg/Bar foo (I)I ALOAD_0 IRETURN local variable array 1 : i 0 : this

slide-81
SLIDE 81

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } ILOAD_1 ICONST_1 IADD INVOKEVIRTUAL pkg/Bar foo (I)I ALOAD_0 IRETURN

  • perand stack

local variable array 1 : i 0 : this

slide-82
SLIDE 82

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } ILOAD_1 ICONST_1 IADD INVOKEVIRTUAL pkg/Bar foo (I)I ALOAD_0 IRETURN

  • perand stack

local variable array 1 : i 0 : this this

slide-83
SLIDE 83

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } ILOAD_1 ICONST_1 IADD INVOKEVIRTUAL pkg/Bar foo (I)I ALOAD_0 IRETURN

  • perand stack

local variable array 1 : i 0 : this i this

slide-84
SLIDE 84

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } ILOAD_1 ICONST_1 IADD INVOKEVIRTUAL pkg/Bar foo (I)I ALOAD_0 IRETURN

  • perand stack

local variable array 1 : i 0 : this 1 this i

slide-85
SLIDE 85

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } ILOAD_1 ICONST_1 IADD INVOKEVIRTUAL pkg/Bar foo (I)I ALOAD_0 IRETURN

  • perand stack

local variable array 1 : i 0 : this this i + 1

slide-86
SLIDE 86

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } ILOAD_1 ICONST_1 IADD INVOKEVIRTUAL pkg/Bar foo (I)I ALOAD_0 IRETURN

  • perand stack

local variable array 1 : i 0 : this foo(i + 1)

slide-87
SLIDE 87

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } ILOAD_1 ICONST_1 IADD INVOKEVIRTUAL pkg/Bar foo (I)I ALOAD_0 IRETURN

  • perand stack

local variable array 1 : i 0 : this

slide-88
SLIDE 88

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } INVOKEVIRTUAL pkg/Bar foo (I)I

  • perand stack

local variable array 1 : i 0 : this 0x2A 0x1B 0x04 0x60 0xAC

slide-89
SLIDE 89

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } } pkg/Bar foo (I)I

  • perand stack

local variable array 1 : i 0 : this 0x2A 0x1B 0x04 0x60 0xAC 0xB6

slide-90
SLIDE 90

source code byte code package pkg; class Bar { int foo(int i) { return foo(i + 1); } }

  • perand stack

local variable array 1 : i 0 : this 0x2A 0x1B 0x04 0x60 0xAC 0xB6 constant pool 0x0002 0x0000 0x0001

slide-91
SLIDE 91

INVOKESTATIC Invokes a static method. pkg/Bar foo ()V

slide-92
SLIDE 92

INVOKEVIRTUAL INVOKESTATIC Invokes a static method. pkg/Bar foo ()V pkg/Bar foo ()V Invokes the most-specific version of an inherited method on a non-interface class.

slide-93
SLIDE 93

INVOKESPECIAL INVOKEVIRTUAL INVOKESTATIC Invokes a static method. pkg/Bar foo ()V pkg/Bar foo ()V Invokes the most-specific version of an inherited method on a non-interface class. pkg/Bar foo ()V Invokes a super class‘s version of an inherited method. Invokes a “constructor method”. Invokes a private method. Invokes an interface default method (Java 8).

slide-94
SLIDE 94

INVOKESPECIAL INVOKEVIRTUAL INVOKESTATIC INVOKEINTERFACE Invokes a static method. pkg/Bar foo ()V pkg/Bar foo ()V Invokes the most-specific version of an inherited method on a non-interface class. pkg/Bar foo ()V Invokes a super class‘s version of an inherited method. Invokes a “constructor method”. Invokes a private method. Invokes an interface default method (Java 8). pkg/Bar foo ()V Invokes an interface method. (Similar to INVOKEVIRTUAL but without virtual method table index optimization.)

slide-95
SLIDE 95

INVOKESPECIAL INVOKEVIRTUAL INVOKESTATIC INVOKEINTERFACE INVOKEDYNAMIC Invokes a static method. pkg/Bar foo ()V pkg/Bar foo ()V Invokes the most-specific version of an inherited method on a non-interface class. pkg/Bar foo ()V Invokes a super class‘s version of an inherited method. Invokes a “constructor method”. Invokes a private method. Invokes an interface default method (Java 8). pkg/Bar foo ()V Invokes an interface method. (Similar to INVOKEVIRTUAL but without virtual method table index optimization.) foo ()V bootstrap Queries the given bootstrap method for locating a method implementation at runtime. (MethodHandle: Combines a specific method and an INVOKE* instruction.)

slide-96
SLIDE 96

INVOKESPECIAL INVOKEVIRTUAL INVOKESTATIC INVOKEINTERFACE INVOKEDYNAMIC Invokes a static method. pkg/Bar foo ()V pkg/Bar foo ()V Invokes the most-specific version of an inherited method on a non-interface class. pkg/Bar foo ()V Invokes a super class‘s version of an inherited method. Invokes a “constructor method”. Invokes a private method. Invokes an interface default method (Java 8). pkg/Bar foo ()V Invokes an interface method. (Similar to INVOKEVIRTUAL but without virtual method table index optimization.) foo ()V bootstrap Queries the given bootstrap method for locating a method implementation at runtime. (MethodHandle: Combines a specific method and an INVOKE* instruction.)

slide-97
SLIDE 97

void foo() { ???(); // invokedynamic } foo() ?

slide-98
SLIDE 98

void foo() { ???(); // invokedynamic } foo() ? bootstrap()

slide-99
SLIDE 99

void foo() { ???(); // invokedynamic } foo() ? bootstrap() bar()

slide-100
SLIDE 100

foo() ? bootstrap() bar() void foo() { bar(); }

slide-101
SLIDE 101

foo() ? bar() void foo() { bar(); }

slide-102
SLIDE 102

foo() ? qux() bar() void foo() { bar(); }

slide-103
SLIDE 103

foo() ? qux() bar() void foo() { bar(); } In theory, this could be achieved by using reflection. However, using invokedynamic

  • ffers a more native approach. This is especially important when dealing with

primitive types (double boxing). Used to implement lambda expressions, more important for dynamic languages.

slide-104
SLIDE 104

@interface Secured { String user(); } class SecurityHolder { static String user = "ANONYMOUS"; }

slide-105
SLIDE 105

class Service { @Secured(user = "ADMIN") void deleteEverything() { // delete everything... } } @interface Secured { String user(); } class SecurityHolder { static String user = "ANONYMOUS"; }

slide-106
SLIDE 106

interface Framework { <T> Class<? extends T> secure(Class<T> type); } class Service { @Secured(user = "ADMIN") void deleteEverything() { // delete everything... } } @interface Secured { String user(); } class SecurityHolder { static String user = "ANONYMOUS"; }

slide-107
SLIDE 107

interface Framework { <T> Class<? extends T> secure(Class<T> type); } class Service { @Secured(user = "ADMIN") void deleteEverything() { // delete everything... } } @interface Secured { String user(); } class SecurityHolder { static String user = "ANONYMOUS"; }

slide-108
SLIDE 108

interface Framework { <T> Class<? extends T> secure(Class<T> type); } class Service { @Secured(user = "ADMIN") void deleteEverything() { // delete everything... } } @interface Secured { String user(); } class SecurityHolder { static String user = "ANONYMOUS"; }

slide-109
SLIDE 109

interface Framework { <T> Class<? extends T> secure(Class<T> type); } class Service { @Secured(user = "ADMIN") void deleteEverything() { // delete everything... } } @interface Secured { String user(); } class SecurityHolder { static String user = "ANONYMOUS"; } does not know about depends on

slide-110
SLIDE 110

interface Framework { <T> Class<? extends T> secure(Class<T> type); } class Service { @Secured(user = "ADMIN") void deleteEverything() { // delete everything... } } @interface Secured { String user(); } class SecurityHolder { static String user = "ANONYMOUS"; } does not know about depends on discovers at runtime

slide-111
SLIDE 111

class Service { @Secured(user = "ADMIN") void deleteEverything() { if(!"ADMIN".equals(UserHolder.user)) { throw new IllegalStateException("Wrong user"); } // delete everything... } } redefine class (build time, agent) class Service { @Secured(user = "ADMIN") void deleteEverything() { // delete everything... } }

slide-112
SLIDE 112

create subclass (Liskov substitution) class SecuredService extends Service { @Override void deleteEverything() { if(!"ADMIN".equals(UserHolder.user)) { throw new IllegalStateException("Wrong user"); } super.deleteEverything(); } } class Service { @Secured(user = "ADMIN") void deleteEverything() { // delete everything... } }

slide-113
SLIDE 113

The “black magic” prejudice. var service = { /* @Secured(user = "ADMIN") */ deleteEverything: function () { // delete everything ... } }

slide-114
SLIDE 114

The “black magic” prejudice. var service = { /* @Secured(user = "ADMIN") */ deleteEverything: function () { // delete everything ... } } function run(service) { service.deleteEverything(); }

slide-115
SLIDE 115

The “black magic” prejudice. var service = { /* @Secured(user = "ADMIN") */ deleteEverything: function () { // delete everything ... } } function run(service) { service.deleteEverything(); } No type, no problem. (“duck typing”)

slide-116
SLIDE 116

The “black magic” prejudice. var service = { /* @Secured(user = "ADMIN") */ deleteEverything: function () { // delete everything ... } } function run(service) { service.deleteEverything(); } In dynamic languages (also those running on the JVM) this concept is applied a lot! For framework implementors, type-safety is conceptually impossible. But with type information available, we are at least able to fail fast when generating code at runtime in case that types do not match. No type, no problem. (“duck typing”)

slide-117
SLIDE 117

class Method { Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException; } class Class { Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException; } Isn’t reflection meant for this?

slide-118
SLIDE 118

class Method { Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException; } class Class { Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException; } Isn’t reflection meant for this? Reflection implies neither type-safety nor a notion of fail-fast. Note: there are no performance gains when using code generation over reflection! Thus, runtime code generation only makes sense for user type enhancement: While the framework code is less type safe, this type-unsafety does not spoil the user‘s code.

slide-119
SLIDE 119

Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(value("Hello World!")) .make() .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); assertThat(dynamicType.newInstance().toString(), is("Hello World!")); Byte Buddy: subclass creation

slide-120
SLIDE 120

Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(value("Hello World!")) .make() .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); assertThat(dynamicType.newInstance().toString(), is("Hello World!")); Byte Buddy: subclass creation

slide-121
SLIDE 121

Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(value("Hello World!")) .make() .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); assertThat(dynamicType.newInstance().toString(), is("Hello World!")); Byte Buddy: subclass creation

slide-122
SLIDE 122

Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(value("Hello World!")) .make() .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); assertThat(dynamicType.newInstance().toString(), is("Hello World!")); Byte Buddy: subclass creation

slide-123
SLIDE 123

Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(value("Hello World!")) .make() .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); assertThat(dynamicType.newInstance().toString(), is("Hello World!")); Byte Buddy: subclass creation

slide-124
SLIDE 124

Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(value("Hello World!")) .make() .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); assertThat(dynamicType.newInstance().toString(), is("Hello World!")); Byte Buddy: subclass creation

slide-125
SLIDE 125

Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(value("Hello World!")) .make() .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); assertThat(dynamicType.newInstance().toString(), is("Hello World!")); Byte Buddy: subclass creation

slide-126
SLIDE 126

Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(value("Hello World!")) .make() .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); assertThat(dynamicType.newInstance().toString(), is("Hello World!")); Byte Buddy: subclass creation

slide-127
SLIDE 127

class MyInterceptor { static String intercept() { return "Hello World"; } } Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(to(MyInterceptor.class)) .make() .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); Byte Buddy: invocation delegation

slide-128
SLIDE 128

class MyInterceptor { static String intercept() { return "Hello World"; } } Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(to(MyInterceptor.class)) .make() .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); Byte Buddy: invocation delegation

slide-129
SLIDE 129

class MyInterceptor { static String intercept() { return "Hello World"; } } identifies best match Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(to(MyInterceptor.class)) .make() .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); Byte Buddy: invocation delegation

slide-130
SLIDE 130

class MyInterceptor { static String intercept(@Origin Method m) { return "Hello World from " + m.getName(); } } Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(to(MyInterceptor.class)) .make() .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); provides arguments Byte Buddy: invocation delegation (2)

slide-131
SLIDE 131

class MyInterceptor { static String intercept(@Origin Method m) { return "Hello World from " + m.getName(); } } Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(to(MyInterceptor.class)) .make() .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); provides arguments Byte Buddy: invocation delegation (2)

slide-132
SLIDE 132

Annotations that are not on the class path are ignored at runtime. Thus, Byte Buddy’s classes can be used without Byte Buddy on the class path. class MyInterceptor { static String intercept(@Origin Method m) { return "Hello World from " + m.getName(); } } Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(to(MyInterceptor.class)) .make() .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); provides arguments Byte Buddy: invocation delegation (2)

slide-133
SLIDE 133

@Origin Method|Class<?>|String Provides caller information @SuperCall Runnable|Callable<?> Allows super method call @DefaultCall Runnable|Callable<?> Allows default method call @AllArguments T[] Provides boxed method arguments @Argument(index) T Provides argument at the given index @This T Provides caller instance @Super T Provides super method proxy Byte Buddy: dependency injection

slide-134
SLIDE 134

class Foo { String bar() { return "bar"; } } Foo foo = new Foo(); new ByteBuddy() .redefine(Foo.class) .method(named("bar")) .intercept(value("Hello World!")) .make() .load(Foo.class.getClassLoader(), ClassReloadingStrategy.installedAgent()); assertThat(foo.bar(), is("Hello World!")); Byte Buddy: runtime Hot Swap

slide-135
SLIDE 135

class Foo { String bar() { return "bar"; } } Foo foo = new Foo(); new ByteBuddy() .redefine(Foo.class) .method(named("bar")) .intercept(value("Hello World!")) .make() .load(Foo.class.getClassLoader(), ClassReloadingStrategy.installedAgent()); assertThat(foo.bar(), is("Hello World!")); Byte Buddy: runtime Hot Swap

slide-136
SLIDE 136

class Foo { String bar() { return "bar"; } } Foo foo = new Foo(); new ByteBuddy() .redefine(Foo.class) .method(named("bar")) .intercept(value("Hello World!")) .make() .load(Foo.class.getClassLoader(), ClassReloadingStrategy.installedAgent()); assertThat(foo.bar(), is("Hello World!")); Byte Buddy: runtime Hot Swap

slide-137
SLIDE 137

class Foo { String bar() { return "bar"; } } Foo foo = new Foo(); new ByteBuddy() .redefine(Foo.class) .method(named("bar")) .intercept(value("Hello World!")) .make() .load(Foo.class.getClassLoader(), ClassReloadingStrategy.installedAgent()); assertThat(foo.bar(), is("Hello World!")); The instrumentation API does not allow introduction of new methods. This might change with JEP-159: Enhanced Class Redefiniton. Byte Buddy: runtime Hot Swap

slide-138
SLIDE 138

class Foo { String bar() { return "bar"; } } assertThat(new Foo().bar(), is("Hello World!")); Byte Buddy: Java agents

slide-139
SLIDE 139

class Foo { String bar() { return "bar"; } } assertThat(new Foo().bar(), is("Hello World!")); public static void premain(String arguments, Instrumentation instrumentation) { new AgentBuilder.Default() .rebase(named("Foo")) .transform( (builder, type) -> builder .method(named("bar")) .intercept(value("Hello World!")); ) .installOn(instrumentation); } Byte Buddy: Java agents

slide-140
SLIDE 140

class Foo { String bar() { return "bar"; } } assertThat(new Foo().bar(), is("Hello World!")); public static void premain(String arguments, Instrumentation instrumentation) { new AgentBuilder.Default() .rebase(named("Foo")) .transform( (builder, type) -> builder .method(named("bar")) .intercept(value("Hello World!")); ) .installOn(instrumentation); } Byte Buddy: Java agents

slide-141
SLIDE 141

class Foo { String bar() { return "bar"; } } assertThat(new Foo().bar(), is("Hello World!")); public static void premain(String arguments, Instrumentation instrumentation) { new AgentBuilder.Default() .rebase(named("Foo")) .transform( (builder, type) -> builder .method(named("bar")) .intercept(value("Hello World!")); ) .installOn(instrumentation); } Byte Buddy: Java agents

slide-142
SLIDE 142

class Foo { String bar() { return "bar"; } } assertThat(new Foo().bar(), is("Hello World!")); public static void premain(String arguments, Instrumentation instrumentation) { new AgentBuilder.Default() .rebase(named("Foo")) .transform( (builder, type) -> builder .method(named("bar")) .intercept(value("Hello World!")); ) .installOn(instrumentation); } Byte Buddy: Java agents

slide-143
SLIDE 143

Android makes things more complicated.

slide-144
SLIDE 144

Java virtual machine [stack, JIT] Android makes things more complicated.

slide-145
SLIDE 145

Java virtual machine [stack, JIT] Dalvik virtual machine [register, JIT] Android makes things more complicated.

slide-146
SLIDE 146

Java virtual machine [stack, JIT] Dalvik virtual machine [register, JIT] Android runtime [register, AOT] Android makes things more complicated.

slide-147
SLIDE 147

Java virtual machine [stack, JIT] Dalvik virtual machine [register, JIT] Android runtime [register, AOT] Android makes things more complicated. Solution: Embed the Android SDK’s dex compiler (Apache 2.0 license). Unfortunately, no recent version central repository deployments of Android SDK.

slide-148
SLIDE 148

Byte Buddy cglib Javassist Java proxy (1) 60.995 234.488 145.412 68.706 (2a) 153.800 804.000 706.878 973.650 (2b) 0.001 0.002 0.009 0.005 (3a) 172.126 1’850.567 1’480.525 625.778 n/a (3b) 0.002 0.003 0.019 0.027 n/a All benchmarks run with JMH, source code: https://github.com/raphw/byte-buddy (1) Extending the Object class without any methods but with a default constructor (2a) Implementing an interface with 18 methods, method stubs (2b) Executing a method of this interface (3a) Extending a class with 18 methods, super method invocation (3b) Executing a method of this class

slide-149
SLIDE 149

http://rafael.codes @rafaelcodes http://documents4j.com https://github.com/documents4j/documents4j http://bytebuddy.net https://github.com/raphw/byte-buddy