This session explores how the Java ecosystem is evolving, by following the lifecycle of the java.lang.invoke package and the invokedynamic bytecode. From its origins in dynamic language optimization to providing the underpinnings of Java 8’s lambda expression, invokedynamic has become a powerful tool for language design.
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
invokedynamic: Evolution of a Language Feature
1. Evolution of a Language Feature
Dan Heidinga, J9 VM Interpreter Lead
Daniel_Heidinga@ca.ibm.com
@DanHeidinga
26 October 2015
Invokedynamic
Brian Goetz, Java Language Architect
Oracle
2. Who am I?
I've been involved with virtual machine development at IBM
since 2007 and am now the J9 Virtual Machine Team Lead.
J9 is IBM's independent implementation of the JVM.
I've represented IBM on both the JSR 292 ('invokedynamic')
and JSR 335 ('lambda') expert groups and lead J9's
implementation of both JSRs.
I’ve also maintain the bytecode verifier and deal with various
other parts of the runtime.
2
3. Who am I?
Brian Goetz is the Java Language Architect at Oracle, and is
one of the leading authorities on the Java platform.
He is the author of the very successful 'Java Concurrency in
Practice', and has published over 75 articles on software
development.
He was the specification lead for JSR-335 (Lambda
Expressions for the Java Language) and has served on
numerous other JCP Expert Groups.
3
4. Important disclaimers
THE INFORMATION CONTAINED IN THIS PRESENTATION IS PROVIDED FOR INFORMATIONAL PURPOSES ONLY.
WHILST EFFORTS WERE MADE TO VERIFY THE COMPLETENESS AND ACCURACY OF THE INFORMATION
CONTAINED IN THIS PRESENTATION, IT IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.
ALL PERFORMANCE DATA INCLUDED IN THIS PRESENTATION HAVE BEEN GATHERED IN A CONTROLLED
ENVIRONMENT. YOUR OWN TEST RESULTS MAY VARY BASED ON HARDWARE, SOFTWARE OR
INFRASTRUCTURE DIFFERENCES.
ALL DATA INCLUDED IN THIS PRESENTATION ARE MEANT TO BE USED ONLY AS A GUIDE.
IN ADDITION, THE INFORMATION CONTAINED IN THIS PRESENTATION IS BASED ON IBM’S CURRENT
PRODUCT PLANS AND STRATEGY, WHICH ARE SUBJECT TO CHANGE BY IBM, WITHOUT NOTICE.
IBM AND ITS AFFILIATED COMPANIES SHALL NOT BE RESPONSIBLE FOR ANY DAMAGES ARISING OUT
OF THE USE OF, OR OTHERWISE RELATED TO, THIS PRESENTATION OR ANY OTHER DOCUMENTATION.
NOTHING CONTAINED IN THIS PRESENTATION IS INTENDED TO, OR SHALL HAVE THE EFFECT OF:
– CREATING ANY WARRANT OR REPRESENTATION FROM IBM, ITS AFFILIATED COMPANIES OR ITS
OR THEIR SUPPLIERS AND/OR LICENSORS
4
5. Danger: highly technical talk!
This talk assumes you’re familiar with:
– JVM bytecode set
– java.lang.invoke.MethodHandle and related classes
– invokedynamic
5
6. Full bleed images preferred
Text over top of full bleed images would be in white or a color from the color palette that
would offer good contrast. Also, colored text in Arial Bold would have greater impact.
9. The JVM: a highly tuned performance machine
https://commons.wikimedia.org/wiki/File:Fernando_Alonso_2010_Jerez_test_14.jpg9
10. It’s fastest when you stay on the path
JVM optimized and tuned for the Java language.
As long as the language maps cleanly to Java’s semantics, good perf is likely
10
11. JVM invoke instructions
Prior to Java 7, there were 4 bytecodes to invoke methods:
– invokespecial: constructors, super calls, private methods
– invokevirtual: receiver based selection of instance methods
– invokestatic: static methods
– invokeinterface: interface based selection of instance methods
The semantics are tightly defined by the JVM spec
11
16. Second class performance citizen: Dynamic languages
Simulation overheads:
– Inlining depth limits
– Inlining bytecode size limits
– Reflection overhead
– Non-inlinable caching / Hashtable lookups
– Type mismatches: sharp types vs IRubyObject
Complexity
– Generating invokers at build time based on annotations
– Need to ensure the cache is correct
16
18. Birth of JSR 292 EG
18
New JVM instruction, invokedynamic, designed to support the
implementation of dynamically typed object oriented languages.
… investigate support for hotswapping
19. The problem: linkage + typing
JVM invoke instructions are tightly tied to Java
– Linkage must match the JVM rules
My language uses different dispatch rules
– Metaclass
– Multiple dispatch
– Mixins
User’s need to control the linkage
19
https://en.wikipedia.org/wiki/Burr_puzzle#/media/File:SixPartWoodKnot.jpg
20. RestartMethodException & VM method cache
Invokedynamic
– like invokevirtual except:
arguments not required to match the method’s signature
support for “doesNotUnderstand” handler
– recursive lookup for method exactly matching descriptor
else call handler, which can:
implement the method & return result
pick a method and return it (via RestartMethodException)
> VM can cache the “restart” method
20
21. From InvokeDynamic to target method
Invokedynamic Target method
21
User supplied
logic
Tell the VM what
method to link to
22. From InvokeDynamic to target method
Invokedynamic
Static data:
Caller
Method name
Descriptor
Other data
Target method
22
User supplied
logic
Tell the VM what
method to link to
BootstrapMethod
23. From InvokeDynamic to target method
Invokedynamic
java.lang.invoke.CallSite
Target method
23
User supplied
logic
Tell the VM what
method to link to
BootstrapMethod
24. From InvokeDynamic to target method
Invokedynamic
java.lang.invoke.CallSite
Target method
24
User supplied
logic
Tell the VM what
method to link to
BootstrapMethod
25. From InvokeDynamic to target method
Invokedynamic Target method
25
java.lang.invoke.CallSite
Indy is permanently linked to the CallSite (1 time)
Invocation of target method can occur many times
26. Anatomy of a CallSite
26
CallSite
type
target
MethodType
(String)V
MethodHandle
link(String)V
27. Anatomy of a CallSite
27
CallSite
type
target
MethodType
(String)V
MethodHandle
link(String)V
The link() handle does two things:
1. It sets CallSite target
2. Completes the call
28. Anatomy of a CallSite
28
CallSite
type
target
MethodType
(String)V
MethodHandle
link(String)V
GuardWithTest
test
target
fallback
MethodHandle
Guard()boolean
MethodHandle
Method(String)V
29. Invokedynamic: bytecode factory
Lazy constants
New semantics
New bytecodes
All these and more can be emulated using invokedynamic
– Bootstrap Method to link the CallSite
– Java code that implements the new operation
– Really the ultimate bytecode emulation tool
29
30. Interface injection
A Class implements all the methods for an interface
Doesn’t declare it implements it
– How can we allow the interface invocation to proceed?
30
Foo foo = new Foo();
if (foo instanceof Injected) {
Injected i = (Injected) foo;
System.out.println(i.m());
}
instanceof
checkcast
invokeinterface
34. [jsr-292-eg] our package name 01/06/2011
Invokedynamic is more than dynamic languages!
Lambda can be built on top of invokedynamic and MethodHandles
(Painfully) renamed the package from java.dyn to java.lang.invoke at development cutoff
34
35. Birth of JSR 292 EG
35
New JVM instruction, invokedynamic, designed to support the
implementation of dynamically typed object oriented languages.
… investigate support for hotswapping
36. Wait, what is a dyn language anyway?
Static Dynamic
36
37. Wait, what is a dyn language anyway?
Static Dynamic
37
Compile
time
Runtime
38. Wait, what is a dyn language anyway?
Static Dynamic
38
Compile
time
Runtime
39. Wait, what is a dyn language anyway?
Static
Typing
Dispatch
Dynamic
Binding
(Un)Loading
39
40. Its not just for dynamic languages anymore
Java 8 gave us Lambda expressions
– But how do we compile this lambda?
40
Predicate<Person> pred = p -> p.age < minAge;
41. Its not just for dynamic languages anymore
So, if indy is for dynamic languages, why is the Java compiler using it?
– All the types involved are static
– We can use indy to give us a dynamic code generation strategy
Generate inner classes?
Use method handles?
Use dynamic proxies?
Use VM-private APIs for constructing objects?
Indy lets us turn this choice into a pure implementation detail
– Separate from the binary representation
41
42. Desugaring lambdas to methods
First, we desugar the lambda to a method
– Signature matches functional interface method
– Plus captured arguments prepended
– Simplest lambdas desugar to static methods
But some need access to receiver, and so are instance methods
42
Predicate<Person> pred = p -> p.age < minAge;
private static boolean lambda$1(int minAge, Person p) {
return p.age < minAge;
}
43. Its not just for dynamic languages anymore
We use indy to embed a recipe for constructing a lambda, including
– The desugared implementation method (static)
– The functional interface we are converting to (static)
– Additional metadata, such as serialization information (static)
– Values captured from the lexical scope (dynamic)
The capture site is called the lambda factory
– Invoked with indy, returns an instance of the desired functional interface
– Subsequent captures bypass the (slow) linkage path
43
44. Factories and metafactories
We generate an indy call site which, when called, returns the lambda
– This is the lambda factory
– Bootstrap for the lambda factory
selects the translation strategy
Bootstrap is called the lambda metafactory
Part of Java runtime
– Captured args passed
to lambda factory
44
list.removeIf(p -> p.age < minAge);
private static boolean lambda$1(int minAge, Person p) {
return p.getAge() >= minAge;
}
Predicate $p = indy[bootstrap=LambdaMetafactory,
staticargs=[Predicate, lambda$1],
dynargs=[minAge])
list.removeIf($p);
45. Full bleed images preferred
Text over top of full bleed images would be in white or a color from the color palette that
would offer good contrast. Also, colored text in Arial Bold would have greater impact.
49. Invoking Specialized Generic Static Methods
We need to capture the type argument at the callsite.
How does m access the type information at run-time?
class C {
static <any T> T m(T i) {…}
}
int i = C.<int>m(3);
50. Embed specialized type information in the invokedynamic Callsite
Invoking Specialized Static Methods (cont’d)
7: iconst_3
8: invokedynamic #4, 0 // InvokeDynamic #0:m:(LFoo;I)V
BootstrapMethods:
0: #26 invokestatic GenericMethodSpecializer.metafactory:
(LMethodHandles$Lookup;LString;LMethodType;[LObject;)LCallSite;
Method arguments:
#27 LC;
#28 invokevirtual C.m:(LObject;)V
#29 I
52. 52
Legal Notice
IBM and the IBM logo are trademarks or registered trademarks of IBM Corporation, in the United States, other
countries or both.
Java and all Java-based marks, among others, are trademarks or registered trademarks of Oracle in the United
States, other countries or both.
Other company, product and service names may be trademarks or service marks of others.
THE INFORMATION DISCUSSED IN THIS PRESENTATION IS PROVIDED FOR INFORMATIONAL
PURPOSES ONLY. WHILE EFFORTS WERE MADE TO VERIFY THE COMPLETENESS AND
ACCURACY OF THE INFORMATION, IT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, AND IBM SHALL NOT BE RESPONSIBLE FOR ANY DAMAGES ARISING OUT
OF THE USE OF, OR OTHERWISE RELATED TO, SUCH INFORMATION. ANY INFORMATION
CONCERNING IBM'S PRODUCT PLANS OR STRATEGY IS SUBJECT TO CHANGE BY IBM WITHOUT
NOTICE.