95
In Vogue Dynamic Alexander Shopov <[email protected]>

In Vogue Dynamic

Embed Size (px)

DESCRIPTION

JSR-292 - How and when to use invokedynamic. Usage in Java 8 for lambdas. Disassembling the code, bootstrap method glue and MethodHandles

Citation preview

Page 1: In Vogue Dynamic

In Vogue Dynamic

Alexander Shopov <[email protected]>

Page 2: In Vogue Dynamic

[ash@edge ~]$ whoamiBy day: Software Engineer at Cisco {,Nov. 28}By night: OSS contributorCoordinator of Bulgarian Gnome TPGit speaks Bulgarian Contacts:

E-mail: [email protected] Jabber: [email protected] LinkedIn: http://www.linkedin.com/in/alshopov SlideShare: http://www.slideshare.net/al_shopovGitHub: https://github.com/alshopovWeb: Just search “al_shopov”

Page 3: In Vogue Dynamic

Please Learn and Share

License: Creative Commons Attribution 4.0 InternationalCC-BY v4.0

Page 4: In Vogue Dynamic

Disclaimer

My opinions, knowledge and experience!Not my employer's.

Page 5: In Vogue Dynamic

Menu for Today

● Numbers● Letters● Sentences● Poetry

Page 6: In Vogue Dynamic

Numbers

Page 7: In Vogue Dynamic

Hundred

100

Page 8: In Vogue Dynamic

Hundred Is a Wonderful Number

100 = (1 + 2 + 3 + 4)²

Page 9: In Vogue Dynamic

Hundred Is a Wonderful Hectonumber

100 = (1 + 2 + 3 + 4)² = 1³ + 2³ + 3³ + 4³

Page 10: In Vogue Dynamic

Hundred Is a Wonderful Hectonumber

100 = (1 + 2 + 3 + 4)² = 1³ + 2³ + 3³ + 4³Νικόμ

αχος

was he

re!

Page 11: In Vogue Dynamic

Hundred Is a Wonderful Hectonumber

100 = (1 + 2 + 3 + 4)² = 1³ + 2³ + 3³ + 4³Νικόμ

αχος

was he

re!A Very BoldComic Sans

Relief

Page 12: In Vogue Dynamic

Triple Hundred Is Even More Magical

100100100

Page 13: In Vogue Dynamic

Triple Hundred by Any Other Base Will Smell as Sweet...

●100100100₂●444₈●292₁₀

Page 14: In Vogue Dynamic

Our Last Numerological Slide…

292

Page 15: In Vogue Dynamic

The One and Only – JSR 292

● JSR 292 specified a new bytecode instruction: invokedynamic– First and only in all the history of Java platform and

technologies.

● There have been retired instructions– jsr, jsr_w – cannot appear in class file version 51.0 (JDK 7.0) and above;

– Together with ret were used for the finally block in Java < 1.5;

– Mainly used for obfuscation.

Page 16: In Vogue Dynamic

Letters

Page 17: In Vogue Dynamic

Bytecode? Who Cares? And It Is Not for Java…

● Well – it is also for Java, especially ≥ 8.0;● And it is also for dynamic languages;● And it is also for static languages;● And it is also for way too many other things;● But – yeah, the lecture is about bytecode, so

this is last chance to leave (run to the hills)…

Page 18: In Vogue Dynamic

Bytecodes Are the Letters of

JVM

Page 19: In Vogue Dynamic

Bytecode Crash Course in 1-2-3-4

Thr

ead

A

F0

F1

F2

F3

F4

Thr

ead

B

F0

F1

F2

Thr

ead

CF0

F1 Thr

ead

D

F0

F1

F2

F3

Page 20: In Vogue Dynamic

Bytecode Crash Course in 1-2-3-4

JVM (heap)

F0

Cla

ss

Pool of constants

0 1 2 3 4 5 6 …

Local variables

Stack

Method codePC

Class

Page 21: In Vogue Dynamic

Bytecode Crash Course in 1-2-3-4● 206 byte sized, typed instructions;● Bytecodes can encode information in themselves, retrieve

things from class bytestream, constant pool, local variables array;

● Perform computations only on stack;● Store temporary results in local variables array (non-visible

after method call);● Store more permanent results in object/class fields (visible

after method call);● Enter frame by method call;● Exit frame by a return from with a possible result (top thing on

stack), or by throwing top of stack;● JVM can also throw and unroll frames;

Page 22: In Vogue Dynamic

Bytecode Crash Course in 1-2-3-4

● You print the bytecode with the javap command:

javap -l -v -p -constants -s -cp CLASSPATH CLASSES

Page 24: In Vogue Dynamic

Most Bytecodes Are Very Dull

● They are lowercase letters – they continue or are a part of a single computational sequence:– The operate on a single stack;

– Inside a single frame;

● They are part of a single method call.

Page 25: In Vogue Dynamic

Sentences

Page 26: In Vogue Dynamic

The Uppercase Bytecodes

● Are the 5 bytecodes that invoke methods (start sentences) in some way.– invokestatic (0xb8)

– invokevirtual (0xb6)

– invokeinterface (0xb9)

– invokespecial (0xb7)

– invokedynamic (0xba)

Page 27: In Vogue Dynamic

The Punctuations

● Just for completeness – there are only 2 ways to end a sentence (method call):– Normal – returning by:

● areturn, dreturn, freturn, ireturn, lreturn, return;

– Abrupt – exception:● Either we throw via athrow● Or the JVM throws itself

Page 28: In Vogue Dynamic

Let's Check Simple Sentences

package org.kambanaria.standardinvoke;

public class Examples { public static int I_STATIC() { int a = Integer.parseInt("7"); return a; }}

Page 29: In Vogue Dynamic

Decompile…

Classfile /Java/StandardInvoke/target/classes/org/kambanaria/standardinvoke/Examples.class Last modified 2014-11-5; size 477 bytes MD5 checksum 2b499f0d33b9e2ed33181349f767bb95 Compiled from "Examples.java"public class org.kambanaria.standardinvoke.Examples SourceFile: "Examples.java" minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPERConstant pool: #1 = Methodref #5.#19 // java/lang/Object."<init>":()V #2 = String #20 // 7 #3 = Methodref #21.#22 // java/lang/Integer.parseInt:(Ljava/lang/String;)I #4 = Class #23 // org/kambanaria/standardinvoke/Examples #5 = Class #24 // java/lang/Object #6 = Utf8 <init> #7 = Utf8 ()V #8 = Utf8 Code #9 = Utf8 LineNumberTable #10 = Utf8 LocalVariableTable #11 = Utf8 this #12 = Utf8 Lorg/kambanaria/standardinvoke/Examples; #13 = Utf8 I_STATIC #14 = Utf8 ()I #15 = Utf8 a #16 = Utf8 I #17 = Utf8 SourceFile #18 = Utf8 Examples.java #19 = NameAndType #6:#7 // "<init>":()V #20 = Utf8 7 #21 = Class #25 // java/lang/Integer #22 = NameAndType #26:#27 // parseInt:(Ljava/lang/String;)I #23 = Utf8 org/kambanaria/standardinvoke/Examples #24 = Utf8 java/lang/Object #25 = Utf8 java/lang/Integer #26 = Utf8 parseInt #27 = Utf8 (Ljava/lang/String;)I

{ public org.kambanaria.standardinvoke.Examples(); Signature: ()V flags: ACC_PUBLIC LineNumberTable: line 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lorg/kambanaria/standardinvoke/Examples; Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lorg/kambanaria/standardinvoke/Examples;

public static int I_STATIC(); Signature: ()I flags: ACC_PUBLIC, ACC_STATIC LineNumberTable: line 6: 0 line 7: 6 LocalVariableTable: Start Length Slot Name Signature 6 2 0 a I Code: stack=1, locals=1, args_size=0 0: ldc #2 // String 7 2: invokestatic #3 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I 5: istore_0 6: iload_0 7: ireturn LineNumberTable: line 6: 0 line 7: 6 LocalVariableTable: Start Length Slot Name Signature 6 2 0 a I}

Page 30: In Vogue Dynamic

But It Is Actually Simple…

Classfile /Java/StandardInvoke/target/classes/org/kambanaria/standardinvoke/Examples.class Last modified 2014-11-5; size 477 bytes MD5 checksum 2b499f0d33b9e2ed33181349f767bb95 Compiled from "Examples.java"public class org.kambanaria.standardinvoke.Examples SourceFile: "Examples.java" minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPERConstant pool: #1 = Methodref #5.#19 // java/lang/Object."<init>":()V #2 = String #20 // 7 #3 = Methodref #21.#22 // java/lang/Integer.parseInt:(Ljava/lang/String;)I #4 = Class #23 // org/kambanaria/standardinvoke/Examples #5 = Class #24 // java/lang/Object #6 = Utf8 <init> #7 = Utf8 ()V #8 = Utf8 Code #9 = Utf8 LineNumberTable #10 = Utf8 LocalVariableTable #11 = Utf8 this #12 = Utf8 Lorg/kambanaria/standardinvoke/Examples; #13 = Utf8 I_STATIC #14 = Utf8 ()I #15 = Utf8 a #16 = Utf8 I #17 = Utf8 SourceFile #18 = Utf8 Examples.java #19 = NameAndType #6:#7 // "<init>":()V #20 = Utf8 7 #21 = Class #25 // java/lang/Integer #22 = NameAndType #26:#27 // parseInt:(Ljava/lang/String;)I #23 = Utf8 org/kambanaria/standardinvoke/Examples #24 = Utf8 java/lang/Object #25 = Utf8 java/lang/Integer #26 = Utf8 parseInt #27 = Utf8 (Ljava/lang/String;)I

{ public org.kambanaria.standardinvoke.Examples(); Signature: ()V flags: ACC_PUBLIC LineNumberTable: line 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lorg/kambanaria/standardinvoke/Examples; Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lorg/kambanaria/standardinvoke/Examples;

public static int I_STATIC(); Signature: ()I flags: ACC_PUBLIC, ACC_STATIC LineNumberTable: line 6: 0 line 7: 6 LocalVariableTable: Start Length Slot Name Signature 6 2 0 a I Code: stack=1, locals=1, args_size=0 0: ldc #2 // String 7 2: invokestatic #3 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I 5: istore_0 6: iload_0 7: ireturn LineNumberTable: line 6: 0 line 7: 6 LocalVariableTable: Start Length Slot Name Signature 6 2 0 a I}

Stats About Class

Constant Pool

Default Constructor

I_STATIC method

Page 31: In Vogue Dynamic

But It Is Actually Very Simple…

Classfile /Java/StandardInvoke/target/classes/org/kambanaria/standardinvoke/Examples.class Last modified 2014-11-5; size 477 bytes MD5 checksum 2b499f0d33b9e2ed33181349f767bb95 Compiled from "Examples.java"public class org.kambanaria.standardinvoke.Examples SourceFile: "Examples.java" minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPERConstant pool: #1 = Methodref #5.#19 // java/lang/Object."<init>":()V #2 = String #20 // 7 #3 = Methodref #21.#22 // java/lang/Integer.parseInt:(Ljava/lang/String;)I #4 = Class #23 // org/kambanaria/standardinvoke/Examples #5 = Class #24 // java/lang/Object #6 = Utf8 <init> #7 = Utf8 ()V #8 = Utf8 Code #9 = Utf8 LineNumberTable #10 = Utf8 LocalVariableTable #11 = Utf8 this #12 = Utf8 Lorg/kambanaria/standardinvoke/Examples; #13 = Utf8 I_STATIC #14 = Utf8 ()I #15 = Utf8 a #16 = Utf8 I #17 = Utf8 SourceFile #18 = Utf8 Examples.java #19 = NameAndType #6:#7 // "<init>":()V #20 = Utf8 7 #21 = Class #25 // java/lang/Integer #22 = NameAndType #26:#27 // parseInt:(Ljava/lang/String;)I #23 = Utf8 org/kambanaria/standardinvoke/Examples #24 = Utf8 java/lang/Object #25 = Utf8 java/lang/Integer #26 = Utf8 parseInt #27 = Utf8 (Ljava/lang/String;)I

{ public org.kambanaria.standardinvoke.Examples(); Signature: ()V flags: ACC_PUBLIC LineNumberTable: line 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lorg/kambanaria/standardinvoke/Examples; Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lorg/kambanaria/standardinvoke/Examples;

public static int I_STATIC(); Signature: ()I flags: ACC_PUBLIC, ACC_STATIC LineNumberTable: line 6: 0 line 7: 6 LocalVariableTable: Start Length Slot Name Signature 6 2 0 a I Code: stack=1, locals=1, args_size=0 0: ldc #2 // String 7 2: invokestatic #3 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I 5: istore_0 6: iload_0 7: ireturn LineNumberTable: line 6: 0 line 7: 6 LocalVariableTable: Start Length Slot Name Signature 6 2 0 a I}

Stats About Class

Constant Pool

Default Constructor

I_STATIC code

I_STATIC stats 1

I_STATIC stats 2

Page 32: In Vogue Dynamic

The Whole Assembler

Code: stack=1, locals=1, args_size=0 0: ldc #2 2: invokestatic #3 5: istore_0 6: iload_0 7: ireturn

Page 33: In Vogue Dynamic

Physical Layout

Code: stack=1, locals=1, args_size=0 0: ldc #2 2: invokestatic #3 5: istore_0 6: iload_0 7: ireturn od -x --endian=big ./Examples.class 02 b8 00 03 3b 1a

0 1 2 3 4 5 6

ac

7

12

Page 34: In Vogue Dynamic

ldc Is 0x12, 1 Byte Reference to Constant Pool

Code: stack=1, locals=1, args_size=0 0: ldc #2 2: invokestatic #3 5: istore_0 6: iload_0 7: ireturn od -x --endian=big ./Examples.class 02 b8 00 03 3b 1a

0 1 2 3 4 5 6

ac

7

12

#2 in Constant Pool:String 7

Page 35: In Vogue Dynamic

invokestatic Is 0xb8, 2 Bytes Reference (00<<8+03==03)

Code: stack=1, locals=1, args_size=0 0: ldc #2 2: invokestatic #3 5: istore_0 6: iload_0 7: ireturn od -x --endian=big ./Examples.class 02 b8 00 03 3b 1a

0 1 2 3 4 5 6

ac

7

12

#3 in Constant Pool points:Method

java/lang/Integer.parseInt:(Ljava/lang/String;)I

Page 36: In Vogue Dynamic

istore_0 Is 0x3b, iload_0 Is 0x1a, ireturn Is 0xac

Code: stack=1, locals=1, args_size=0 0: ldc #2 2: invokestatic #3 5: istore_0 6: iload_0 7: ireturn od -x --endian=big ./Examples.class 02 b8 00 03 3b 1a

0 1 2 3 4 5 6

ac

7

12

Page 37: In Vogue Dynamic

Let's Check Another Sentence

public static void I_VIRTUAL() throws InterruptedException { "7".wait(3, 7); }

Page 38: In Vogue Dynamic

As Before – Push Arguments Onto Stack, Invoke Name + Signature

public static void I_VIRTUAL()Code: 0: ldc #2 // String 7 2: ldc2_w #4 // long 3l 5: bipush 7 7: invokevirtual #6 // Method java/lang/Object.wait:(JI)V10: return

Page 39: In Vogue Dynamic

Let's Check the Rest of Old Invoke Instructions

public static int I_INTERFACE(){ return "7".compareTo("8"); } public static Object I_SPECIAL(){ return new Integer(5); } // also private methods, super

Page 40: In Vogue Dynamic

As Before – Push Arguments Onto Stack, Invoke Name + Signature

I_INTERFACE();Code:0: ldc #2 // "7"2: ldc #7 // "8"4: invokevirtual #8// Method // String.compareTo7: ireturn

I_SPECIAL();Code:0: new #9//class j/l/Integer3: dup4: iconst_55: invokespecial #10//Method Integer.//"<init>":(I)V8: areturn

Page 41: In Vogue Dynamic

Fundamentally Traditional ∀Invokes:

● Are scoped Java-ish (class or interface);● Have a Java-ish receiver (single or none);● And definitely do Java-ish dispatch;● Everything else – you have to simulate.

Page 42: In Vogue Dynamic

Now Here Comes Java 8, Functional Interfaces, Lambdas

public static void notEmpty(Collection<String> all) { all.removeIf(String::isEmpty);}

Page 43: In Vogue Dynamic

Which is Syntactic Sugar for an Anonymous Inner Class

public static void notEmptyOld(Collection<String> all) { all.removeIf(new Predicate<String>() { @Override public boolean test(String t) { return t.isEmpty(); } });}

Page 44: In Vogue Dynamic

Which is Syntactic Sugar For An Anonymous Inner Class

public static void notEmptyOld(Collection<String> all) { all.removeIf(new Predicate<String>() { @Override public boolean test(String t) { return t.isEmpty(); } });}

New ObjectPer Invocation

Page 45: In Vogue Dynamic

Which is Syntactic Sugar For An Anonymous Inner Class

public static void notEmptyOld(Collection<String> all) { all.removeIf(new Predicate<String>() { @Override public boolean test(String t) { return t.isEmpty(); } });}

New ObjectPer Invocation

A Whole NewClass

Page 46: In Vogue Dynamic

Improve by Caching

public static void nonEmptyOldNeat(Collection<String> all) { all.removeIf(nonEmptyP);}

private static Predicate<String>nonEmptyP = new Predicate<String>() { @Override public boolean test(String t) { return t.isEmpty(); }};

Page 47: In Vogue Dynamic

Improve by Caching

public static void nonEmptyOldNeat(Collection<String> all) { all.removeIf(nonEmptyP);}

private static Predicate<String>nonEmptyP = new Predicate<String>() { @Override public boolean test(String t) { return t.isEmpty(); }};

A Whole NewClass

Page 48: In Vogue Dynamic

Let's Disassemble nonEmpty

nonEmpty Code: 0: aload_0 //Load ref to col on stack 1: invokedynamic #2, 0 // Here's Waldo // Magic! 6: invokeinterface #3, 2 // Collection.removeIf 11: pop // pop boolean from stack 12: return // we are ready}

Page 49: In Vogue Dynamic

Let's Disassemble nonEmpty

1: invokedynamic #2, 0// That is ba 00 02 00 00 when dumped// #2 in constant pool is: InvokeDynamic #0:test:()Ljava/util/function/Predicate;// void -> Predicate, has index 0, OK // Where is String.isEmpty?

Page 50: In Vogue Dynamic

At the End of the Class

BootstrapMethods:0: #25 invokestatic j/l/invoke/LambdaMetafactory.metafactory:( Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/invoke/MethodType; Ljava/lang/invoke/MethodHandle; Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;

Method arguments: #26 (Ljava/lang/Object;)Z #27 invokevirtual j/l/String.isEmpty:()Z #28 (Ljava/lang/String;)Z

Page 51: In Vogue Dynamic

At the End of the Class

BootstrapMethods:0: #25 invokestatic j/l/invoke/LambdaMetafactory.metafactory:( Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/invoke/MethodType; Ljava/lang/invoke/MethodHandle; Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;

Method arguments: #26 (Ljava/lang/Object;)Z #27 invokevirtual j/l/String.isEmpty:()Z #28 (Ljava/lang/String;)Z

Index 0

Page 52: In Vogue Dynamic

At the End of the Class

BootstrapMethods:0: #25 invokestatic j/l/invoke/LambdaMetafactory.metafactory:( Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/invoke/MethodType; Ljava/lang/invoke/MethodHandle; Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;

Method arguments: #26 (Ljava/lang/Object;)Z #27 invokevirtual j/l/String.isEmpty:()Z #28 (Ljava/lang/String;)Z

Fat Factory – Gives CallSite, not

Predicate

Page 53: In Vogue Dynamic

At the End of the Class

BootstrapMethods:0: #25 invokestatic j/l/invoke/LambdaMetafactory.metafactory:( Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/invoke/MethodType; Ljava/lang/invoke/MethodHandle; Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;

Method arguments: #26 (Ljava/lang/Object;)Z #27 invokevirtual j/l/String.isEmpty:()Z #28 (Ljava/lang/String;)Z

Here Is the Test

Page 54: In Vogue Dynamic

Let's Try a More Realistic nonEmpty

public static void nonEmpty(Collection<String> all) { all.removeIf(s -> s == null || s.trim().isEmpty());}

Page 55: In Vogue Dynamic

The nonEmpty Method Stays the Same

nonEmpty Code: 0: aload_0 //Load ref to col on stack 1: invokedynamic #2, 0 // Here's Waldo // Magic! 6: invokeinterface #3, 2 // Collection.removeIf 11: pop // pop boolean from stack 12: return // we are ready}

Page 56: In Vogue Dynamic

We Get a Private, Static, Synthetic Method lambda$nonEmpty$0

lambda$nonEmpty$0 // (Ljava/lang/String;)Z Code: 0: aload_0 1: ifnull 14 4: aload_0 5: invokevirtual #4 // String.trim 8: invokevirtual #5 // String.isEmpty 11: ifeq 18 14: iconst_1 15: goto 19 18: iconst_0 19: ireturn

Page 57: In Vogue Dynamic

Which in Java Terms is

private static void lambda$nonEmpty$0(String s) { return s == null || s.trim().isEmpty();}

Page 58: In Vogue Dynamic

The Bootstap Glue Becomes

BootstrapMethods:0: #23 invokestatic j/l/invoke/LambdaMetafactory.metafactory:( Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/invoke/MethodType; Ljava/lang/invoke/MethodHandle; Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;

Method arguments: #24 (Ljava/lang/Object;)Z #25 invokestatic org/kambanaria/invokedynamic/ Examples.lambda$nonEmpty$0:(Ljava/lang/String;)Z #26 (Ljava/lang/String;)Z

Page 59: In Vogue Dynamic

Seems We Are Winning

● Lambdas get to be called with invokedynamic● Which refers some glue code (bootstrap

method)● Which refers either:

– Some existing method (String::isEmpty);

– A new custom method (lambda$nonEmpty$0).

● No need to reuse a static instance;● No new inner class!

Page 60: In Vogue Dynamic

Another Win for the Fundamental Theorem of Software Engineering

● David Wheeler● But what is that theorem?

Page 61: In Vogue Dynamic

The Traditional Invoke Instructions

● Have a precise Java-ish meaning;● They point to some executable code by:

– Name;

– Signature.● Somewhat eased by boxing/varargs.

– What they actually point to is a string in the constant pool that gives name + signature.

● Given that – JVM does a predefined resolution.

Page 62: In Vogue Dynamic

JVM

Old Invokes

invoke

type

Name+

signature

JVM

Methodcode

Methodcode

Methodcode

Decision by JVM

Page 63: In Vogue Dynamic

JVM

Invokedynamic – We Get to Decide(This Is not the Whole Picture)

invoke

dynamic

BootstrapMethod→CallSite

JVM

Methodcode

Methodcode

Methodcode

MethodHandle

Decision by Us Decision by Us

Decision by Us

Page 64: In Vogue Dynamic

The Fundamental Theorem of Software Engineering

All problems in computer science can be solved by another level of indirection, except of course for the problem of too many indirections.

David Wheeler

Page 65: In Vogue Dynamic

Poetry

Page 66: In Vogue Dynamic

Prose ↔ Poetry

● Using invokedynamic we can tell the JVM that a particular phrase (callsite) points to a particular code – has a particular meaning;– This can be very dull, repetitive and prosaic;

● In poetry – you can talk about one thing but mean another;– And even when things are ambiguous or just not

the right types, number or order – it works fine;

– And it is always in vogue;

– And as rapping has shown – it can be fast!

Page 67: In Vogue Dynamic

How Does Invokedynamic Exactly Work

● A dynamic call site is every lexical occurrence of invokedynamic;– Thus EVERY occurrence can behave differently;

● The instruction is followed by 4 bytes, only the fist 2 of them are currently used, the rest must be 0;

● The 1st 2 bytes point to an index in the constant that contains a call site specifier that leads to a j.l.invoke.MethodHandle that serves as a bootstrap method;

● The bootstrap method is invoked and returns a j.l.invoke.CallSite, this is bound permanently to this call site;

● The CallSite object provides a MethodHandle via getTarget() method which provides the exact behavior.

● The result of getTarget() CAN change!

Page 68: In Vogue Dynamic

JVM

Invokedynamic

invoke

dynamic

JVM

Methodcode

Methodcode

Methodcode

Page 69: In Vogue Dynamic

JVM

Invokedynamic

invoke

dynamic

MethodHandle

Bootstrap

JVM

Methodcode

Methodcode

Methodcode

Page 70: In Vogue Dynamic

JVM

Invokedynamic

invoke

dynamic

MethodHandle

Bootstrap

JVM

Methodcode

Methodcode

Methodcode

CallSite

Page 71: In Vogue Dynamic

JVM

Invokedynamic

invoke

dynamic

MethodHandle

Bootstrap

JVM

Methodcode

Methodcode

Methodcode

CallSite

Page 72: In Vogue Dynamic

JVMC

allS

ite

Invokedynamic

invoke

dynamic

JVM

Methodcode

Methodcode

Methodcode

Page 73: In Vogue Dynamic

JVMC

allS

ite

Invokedynamic

invoke

dynamic

JVM

Methodcode

Methodcode

Methodcode

MethodHandle

MethodHandle

MethodHandle

Page 74: In Vogue Dynamic

JVMC

allS

ite

Invokedynamic

invoke

dynamic

JVM

Methodcode

Methodcode

Methodcode

MethodHandle

MethodHandle

MethodHandle

Page 75: In Vogue Dynamic

JVMC

allS

ite

Invokedynamic

invoke

dynamic

JVM

Methodcode

Methodcode

Methodcode

MethodHandle

MethodHandle

MethodHandle

Page 76: In Vogue Dynamic

MethodHandles vs. Reflection

● Reflections allows you to look at yourself and discover things, they are closer to Java language constructs;

● MethodHadles assume you know what you are looking for – no exploration, but they are closer to the way JVM functions – they are fast.– Using them is like shaving in the dark – you have to

know where the razor is, how much foam to squeeze, what you are shaving but you can do it fast since your hands know their way – they have memory of their own.

Page 77: In Vogue Dynamic

But Wait – Types Must Match!

● You cannot pass some number of arguments to a method that expects another number– Except varargs

● You cannot pass different types of arguments– Except boxing/unboxing

● You cannot reorder;● You cannot group;● You cannot aggregate.

Page 78: In Vogue Dynamic

You Cannot Put a Square Peg In a Round Whole

Page 79: In Vogue Dynamic

But You Actually Can

Page 80: In Vogue Dynamic

Reshape the Peg to Be No Longer Square But Round and It Fits

Page 81: In Vogue Dynamic

JVMC

allS

ite

Method Handles Know Types

invoke

dynamic

JVM

Methodcode

Methodcode

Methodcode

MethodHandle

MethodHandle

Page 82: In Vogue Dynamic

JVMC

allS

ite

But You Can Convert/Reshape/ Rechisel the JVM Way

invoke

dynamic

JVM

Methodcode

Methodcode

Methodcode

MethodHandle

MethodHandle

MethodHandle

MethodHandle

Page 83: In Vogue Dynamic

java.lang.invoke In a Nutshell

● CallSite (Constant/Mutable/Volatile) – produces MethodHandle

● MethodType – represents types● MethodHandle – reference to method, (static) field, array

member access;● MethodHandles – combining or producing handles;● MethodHandles.Lookup – get a MethodHandle referring to

actual method, filed, array member;● MethodHandleProxies – proxies – interface-handle;● SwitchPoint – fast, one-way if-then-else for handles;

Page 84: In Vogue Dynamic

Example – Curry

public class Computer { public static int sum (int a, int b){ return a + b; }}

Page 85: In Vogue Dynamic

Example – Curry

Computer.sum(2, 7); // => 9// What we can seeMethodHandles.Lookup lookUp = MethodHandles.lookup();MethodType sumType = MethodType.methodType( // result, 1 arg, , 2 arg int.class, int.class, int.class);MethodHandle sumHandle = lookUp.findStatic( Computer.class, "sum", sumType);sumHandle.invoke(2, 7); // => 9MethodHandle add2Handle = MethodHandles. insertArguments(sumHandle, 0, 2);add2Handle.invokeWithArguments(7); // => 9

Page 86: In Vogue Dynamic

Example – Switch Receiver and Arg

"tom".concat("cat"); // => "tomcat""cat".concat("tom"); // => "cattom"

Page 87: In Vogue Dynamic

Example – Switch Receiver and Argument

MethodType catType = MethodType.methodType(// result, argument String.class, String.class);MethodHandle catHandle = lookUp.findVirtual( String.class, "concat",catType);catHandle.invoke("tom", "cat"); // "tomcat"

MethodType tacType = MethodType.methodType(// result, receiver, argument String.class, String.class, String.class);MethodHandle tacHandle = MethodHandles. permuteArguments(catHandle, tacType, 1, 0);tacHandle.invoke("tom", "cat"); // "cattom"

Page 88: In Vogue Dynamic

Rhymes And Allusions

● Rhymes get from repetition of sounds – and you get to make MethodHandles from other MethodHadles all the way turtles go;

● You can adapt and convert types – thus you can use a MethotHandle with one type for something else – with a different type. You can write one stanza but use it for many contexts;

● JVM actually understands this algebra of handles and types and can optimize it.

Page 89: In Vogue Dynamic

If You Are Not So Much Into Poetry

Page 90: In Vogue Dynamic

Shameless Plug for Geertjan & NetBeans

Page 91: In Vogue Dynamic

Shameless Plug for Geertjan & NetBeans

Page 92: In Vogue Dynamic

Shameless Plug for Geertjan & NetBeans

Page 93: In Vogue Dynamic

Shameless Plug for Geertjan & NetBeans

Page 94: In Vogue Dynamic

Further Resources

● Nutter, Ch. (headius – JRuby guy)– Invokedynamic: Changing the JVM Forever

– Invokedynamic in 45 minutes– Indy Deep Dive

● Worthington, J.: Using invokedynamic to teach the JVM a new language

● Rose, J.: Bytecodes meet combinators: invokedynamic on the JVM

● Ponge, J: Demystifying invokedynamic, Java Magazine 2013, January-February: Part 1, May-June: Part 2

● Forax, R.: jsr292-cookbook

Page 95: In Vogue Dynamic

Images

● rosipaw: 146/365 square peg into a round holeCC BY-NC-SA 2.0

● Eric: Lego Porn CC BY-NC-SA 2.0