Exploring lambdas and 
invokedynamic for embedded 
systems 
Stephan E. Korsholm 
sek@viauc.dk 
VIA University College, Horsens, DK 
seminar, CISS 
Aalborg November 24th 2014 1
Overview 
• What I have discovered about lambda expressions (closures) 
and invokedynamic 
- as seen from Java space 
- and from the class files 
• Current support in the HVM (an embedded execution 
environment for Java) 
• The Java virtual machine specification and why it violates 
common software design principles, especially for 
invokedynamic 
• Comments, discussions and on-the-fly experimentation 
encouraged! 
2
Closures in Java 
3 
package test; 
public class TestInvokeDynamic7 { 
private static void print(String str) { 
devices.Console.println(str); 
} 
private interface Action { 
void doIt(); 
} 
public static void main(String[] args) { 
Action action = () -> print("Hello Lambda!"); 
action.doIt(); 
} 
} 
Functional interface 
The closure 
Executing the closure
Closures in Java 
4 
• The functional interface declaration is required 
• Closures are references to methods – possibly anonymous 
like in the example – but can also be to named methods 
(example follows later) 
• The method reference are typed as the instances of the 
functional interface 
• The functional interface can only have 1 method declaration 
package test; 
public class TestInvokeDynamic7 { 
private static void print(String str) { 
devices.Console.println(str); 
} 
private interface Action { 
void doIt(); 
} 
public static void main(String[] args) { 
Action action = () -> print("Hello Lambda!"); 
action.doIt(); 
} 
}
Closures in Java 
5 
Compiled from "TestInvokeDynamic7.java" 
public class test.TestInvokeDynamic7 { 
public test.TestInvokeDynamic7(); 
Code: 
0: aload_0 
1: invokespecial #8 // Method java/lang/Object."<init>":()V 
4: return 
public static void main(java.lang.String[]); 
Code: 
0: invokedynamic #28, 0 // InvokeDynamic #0:doIt: 
//()Ltest/TestInvokeDynamic7$Action; 
5: astore_1 
6: aload_1 
7: invokeinterface #29, 1 // InterfaceMethod 
// test/TestInvokeDynamic7$Action.doIt: 
// ()V 
12: aconst_null 
13: astore_0 
14: return 
}
Closures in Java 
• The invokedynamic bytecode does not invoke the closure – 
6 
it creates an instance of the functional interface 
• The closure is invoked using the standard bytecode 
invokeinterface 
Compiled from "TestInvokeDynamic7.java" 
public class test.TestInvokeDynamic7 { 
public test.TestInvokeDynamic7(); 
Code: 
0: aload_0 
1: invokespecial #8 // Method java/lang/Object."<init>":()V 
4: return 
public static void main(java.lang.String[]); 
Code: 
0: invokedynamic #28, 0 // InvokeDynamic #0:doIt: 
//()Ltest/TestInvokeDynamic7$Action; 
5: astore_1 
6: aload_1 
7: invokeinterface #29, 1 // InterfaceMethod 
// test/TestInvokeDynamic7$Action.doIt: 
// ()V 
12: aconst_null 
13: astore_0 
14: return 
}
Closures in Java 
7 
package test; 
public class TestInvokeDynamic7 { 
private static void print(String str) { 
devices.Console.println(str); 
} 
private interface Action { 
void doIt(); 
} 
private static class MyAction implements Action 
{ 
@Override 
public void doIt() { 
print("Hello Lambda!"); 
} 
} 
public static void main(String[] args) { 
MyAction myAction = new MyAction(); 
Action action = myAction::doIt; 
action.doIt(); 
} 
}
Closures in Java 
8 
package test; 
public class TestInvokeDynamic7 { 
private static void print(String str) { 
devices.Console.println(str); 
} 
private interface Action { 
void doIt(); 
} 
private static class MyAction implements Action 
{ 
@Override 
public void doIt() { 
print("Hello Lambda!"); 
} 
} 
public static void main(String[] args) { 
MyAction myAction = new MyAction(); 
Action action = myAction::doIt; 
action.doIt(); 
} 
} 
This can be removed!
Closures in Java 
9 
package test; 
public class TestInvokeDynamic7 { 
private static void print(String str) { 
devices.Console.println(str); 
} 
private interface Action { 
void doIt(); 
} 
private static class MyAction 
{ 
public void doIt() { 
print("Hello Lambda!"); 
} 
} 
public static void main(String[] args) { 
MyAction myAction = new MyAction(); 
Action action = myAction::doIt; 
action.doIt(); 
} 
} 
This name can be anything!
Closures in Java 
10 
package test; 
public class TestInvokeDynamic7 { 
private static void print(String str) { 
devices.Console.println(str); 
} 
private interface Action { 
void doIt(); 
} 
private static class MyAction 
{ 
public void foo() { 
print("Hello Lambda!"); 
} 
} 
public static void main(String[] args) { 
MyAction myAction = new MyAction(); 
Action action = myAction::foo; 
action.doIt(); 
} 
}
Closures in Java 
11 
package test; 
public class TestInvokeDynamic7 { 
private static void print(String str) { 
devices.Console.println(str); 
} 
private interface Action { 
void doIt(); 
} 
private static class MyAction 
{ 
public void foo() { 
print("Hello Lambda!"); 
} 
} 
public static void main(String[] args) { 
MyAction myAction = new MyAction(); 
Action action = myAction::foo; 
action.doIt(); 
} 
} 
This can be static as well!
Closures in Java 
12 
package test; 
public class TestInvokeDynamic7 { 
private static void print(String str) { 
devices.Console.println(str); 
} 
private interface Action { 
void doIt(); 
} 
private static void foo() { 
print("Hello Lambda!"); 
} 
public static void main(String[] args) { 
Action action = TestInvokeDynamic7::foo; 
action.doIt(); 
} 
}
Closures in Java 
13 
• A closure is conceptually a reference to a method! 
• References to object fields? 
• References to static fields? 
• Other??
Closures in Java 
• The invokedynamic bytecode is similar to new in its effect – 
it creates an instance of a class (that has 1 method declared) 
• To implement invokedynamic in the JVM the following must 
14 
be known, 
- Which functional interface is being instantiated? 
- Which method (class name, method name, method 
signature)? 
• The JVM calls a bootstrap method with a series of arguments 
- The bootstrap method is 
LambdaMethodFactory.metafactory 
- It generates a CallSite instance 
- This has a MethodHandle that returns an instance of the 
functional interface when invoked
Closures in Java 
15 
• The closure can only reference final context! 
- How is this in Scheme/Lisp? 
- How is this in C#? 
• Can the bootstrap method be something else – a user 
specified bootstrap method? 
•
Closures in Java – how the HVM 
does it 
16 
• Calling LambdaMethodFactory.metafactory is not 
possible – the dependcy extent is too large 
• The HVM must simulate that functionality 
• Current level of support – demonstrate.....
Closures in Java – how the HVM 
does it 
17 
1) Invokedynamic is 3 bytes – last 2 bytes is a short index into the constant pool of 
the enclosing class 
2) There is a ConstantInvokeDynamic at that index (new in Java 8) 
3) It contains a BootstrapMethodIndex and a NameAndType 
4) The NameAndType gives the functional interface method and signature 
5) Then the enclosing class is searched for a BootstrapMethods attribute. This 
contains a single(?) BootstrapMethod 
6) This contains a bootstrapMethodRef and a list of bootstrap arguments 
7) The bootstrapMethodRef is a ConstantMethodHandle – it has a 
referenceKind and a ConstantMethodref 
8) The ConstantMethodref refers the bootstrap method 
(LambdaMethodFactory.metafactory) 
9) Then the bootstrap arguments are scanned, looking for a ConstantMethodHandle 
10) This handle has (as above) a a referenceKind and a ConstantMethodref 
11) The ConstantMethodref refers the closure method (containing class, name and 
signature) 
12) If the method is an anonymous method it is called 'lambda$X' and is placed in the 
enclosing class
Closures in Java – how the HVM 
does it 
• We now have (1) the functional interface being implemented, 
• (2) The bootstrap method, and 
• (3) The actual method containing the bytecode of the closure 
• Now the HVM does the following, 
╶ Throws away the bootstrap method (not used) 
╶ Creates a synthetic class containing one method which is the 
method with the bytecode of the closure 
╶ Changes the name of the method to be the same as the name 
declared in the interface 
╶ Now this class is added to the pool of classes managed by 
the HVM as if it were an ordinary class 
╶ Invokedynamic becomes the same as new, we know which 
class to instantiate (the synthetic class) 
18
Closures in Java – how the HVM 
does it 
19 
• What about the other reference kinds? 
• Why are there (potentially) more bootstrap methods? 
• What are the other arguments to the bootstrap method? 
• Will it always be possible to determine the actual closure 
method at compile time?
The Java VM spec and software 
design principles 
20 
• Layered software architecture. Only references down the 
stack (DECT, TCP, …) 
• iadd is a good well behaved byte code 
• idiv is not quite so well behaved – requires the presence of 
java.lang.ArithmeticException 
• invokedynamic is not well behaved – requires the presence 
of a multitude of API classes 
• Dependencies are up the stack – not down

Exploring lambdas and invokedynamic for embedded systems

  • 1.
    Exploring lambdas and invokedynamic for embedded systems Stephan E. Korsholm sek@viauc.dk VIA University College, Horsens, DK seminar, CISS Aalborg November 24th 2014 1
  • 2.
    Overview • WhatI have discovered about lambda expressions (closures) and invokedynamic - as seen from Java space - and from the class files • Current support in the HVM (an embedded execution environment for Java) • The Java virtual machine specification and why it violates common software design principles, especially for invokedynamic • Comments, discussions and on-the-fly experimentation encouraged! 2
  • 3.
    Closures in Java 3 package test; public class TestInvokeDynamic7 { private static void print(String str) { devices.Console.println(str); } private interface Action { void doIt(); } public static void main(String[] args) { Action action = () -> print("Hello Lambda!"); action.doIt(); } } Functional interface The closure Executing the closure
  • 4.
    Closures in Java 4 • The functional interface declaration is required • Closures are references to methods – possibly anonymous like in the example – but can also be to named methods (example follows later) • The method reference are typed as the instances of the functional interface • The functional interface can only have 1 method declaration package test; public class TestInvokeDynamic7 { private static void print(String str) { devices.Console.println(str); } private interface Action { void doIt(); } public static void main(String[] args) { Action action = () -> print("Hello Lambda!"); action.doIt(); } }
  • 5.
    Closures in Java 5 Compiled from "TestInvokeDynamic7.java" public class test.TestInvokeDynamic7 { public test.TestInvokeDynamic7(); Code: 0: aload_0 1: invokespecial #8 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: invokedynamic #28, 0 // InvokeDynamic #0:doIt: //()Ltest/TestInvokeDynamic7$Action; 5: astore_1 6: aload_1 7: invokeinterface #29, 1 // InterfaceMethod // test/TestInvokeDynamic7$Action.doIt: // ()V 12: aconst_null 13: astore_0 14: return }
  • 6.
    Closures in Java • The invokedynamic bytecode does not invoke the closure – 6 it creates an instance of the functional interface • The closure is invoked using the standard bytecode invokeinterface Compiled from "TestInvokeDynamic7.java" public class test.TestInvokeDynamic7 { public test.TestInvokeDynamic7(); Code: 0: aload_0 1: invokespecial #8 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: invokedynamic #28, 0 // InvokeDynamic #0:doIt: //()Ltest/TestInvokeDynamic7$Action; 5: astore_1 6: aload_1 7: invokeinterface #29, 1 // InterfaceMethod // test/TestInvokeDynamic7$Action.doIt: // ()V 12: aconst_null 13: astore_0 14: return }
  • 7.
    Closures in Java 7 package test; public class TestInvokeDynamic7 { private static void print(String str) { devices.Console.println(str); } private interface Action { void doIt(); } private static class MyAction implements Action { @Override public void doIt() { print("Hello Lambda!"); } } public static void main(String[] args) { MyAction myAction = new MyAction(); Action action = myAction::doIt; action.doIt(); } }
  • 8.
    Closures in Java 8 package test; public class TestInvokeDynamic7 { private static void print(String str) { devices.Console.println(str); } private interface Action { void doIt(); } private static class MyAction implements Action { @Override public void doIt() { print("Hello Lambda!"); } } public static void main(String[] args) { MyAction myAction = new MyAction(); Action action = myAction::doIt; action.doIt(); } } This can be removed!
  • 9.
    Closures in Java 9 package test; public class TestInvokeDynamic7 { private static void print(String str) { devices.Console.println(str); } private interface Action { void doIt(); } private static class MyAction { public void doIt() { print("Hello Lambda!"); } } public static void main(String[] args) { MyAction myAction = new MyAction(); Action action = myAction::doIt; action.doIt(); } } This name can be anything!
  • 10.
    Closures in Java 10 package test; public class TestInvokeDynamic7 { private static void print(String str) { devices.Console.println(str); } private interface Action { void doIt(); } private static class MyAction { public void foo() { print("Hello Lambda!"); } } public static void main(String[] args) { MyAction myAction = new MyAction(); Action action = myAction::foo; action.doIt(); } }
  • 11.
    Closures in Java 11 package test; public class TestInvokeDynamic7 { private static void print(String str) { devices.Console.println(str); } private interface Action { void doIt(); } private static class MyAction { public void foo() { print("Hello Lambda!"); } } public static void main(String[] args) { MyAction myAction = new MyAction(); Action action = myAction::foo; action.doIt(); } } This can be static as well!
  • 12.
    Closures in Java 12 package test; public class TestInvokeDynamic7 { private static void print(String str) { devices.Console.println(str); } private interface Action { void doIt(); } private static void foo() { print("Hello Lambda!"); } public static void main(String[] args) { Action action = TestInvokeDynamic7::foo; action.doIt(); } }
  • 13.
    Closures in Java 13 • A closure is conceptually a reference to a method! • References to object fields? • References to static fields? • Other??
  • 14.
    Closures in Java • The invokedynamic bytecode is similar to new in its effect – it creates an instance of a class (that has 1 method declared) • To implement invokedynamic in the JVM the following must 14 be known, - Which functional interface is being instantiated? - Which method (class name, method name, method signature)? • The JVM calls a bootstrap method with a series of arguments - The bootstrap method is LambdaMethodFactory.metafactory - It generates a CallSite instance - This has a MethodHandle that returns an instance of the functional interface when invoked
  • 15.
    Closures in Java 15 • The closure can only reference final context! - How is this in Scheme/Lisp? - How is this in C#? • Can the bootstrap method be something else – a user specified bootstrap method? •
  • 16.
    Closures in Java– how the HVM does it 16 • Calling LambdaMethodFactory.metafactory is not possible – the dependcy extent is too large • The HVM must simulate that functionality • Current level of support – demonstrate.....
  • 17.
    Closures in Java– how the HVM does it 17 1) Invokedynamic is 3 bytes – last 2 bytes is a short index into the constant pool of the enclosing class 2) There is a ConstantInvokeDynamic at that index (new in Java 8) 3) It contains a BootstrapMethodIndex and a NameAndType 4) The NameAndType gives the functional interface method and signature 5) Then the enclosing class is searched for a BootstrapMethods attribute. This contains a single(?) BootstrapMethod 6) This contains a bootstrapMethodRef and a list of bootstrap arguments 7) The bootstrapMethodRef is a ConstantMethodHandle – it has a referenceKind and a ConstantMethodref 8) The ConstantMethodref refers the bootstrap method (LambdaMethodFactory.metafactory) 9) Then the bootstrap arguments are scanned, looking for a ConstantMethodHandle 10) This handle has (as above) a a referenceKind and a ConstantMethodref 11) The ConstantMethodref refers the closure method (containing class, name and signature) 12) If the method is an anonymous method it is called 'lambda$X' and is placed in the enclosing class
  • 18.
    Closures in Java– how the HVM does it • We now have (1) the functional interface being implemented, • (2) The bootstrap method, and • (3) The actual method containing the bytecode of the closure • Now the HVM does the following, ╶ Throws away the bootstrap method (not used) ╶ Creates a synthetic class containing one method which is the method with the bytecode of the closure ╶ Changes the name of the method to be the same as the name declared in the interface ╶ Now this class is added to the pool of classes managed by the HVM as if it were an ordinary class ╶ Invokedynamic becomes the same as new, we know which class to instantiate (the synthetic class) 18
  • 19.
    Closures in Java– how the HVM does it 19 • What about the other reference kinds? • Why are there (potentially) more bootstrap methods? • What are the other arguments to the bootstrap method? • Will it always be possible to determine the actual closure method at compile time?
  • 20.
    The Java VMspec and software design principles 20 • Layered software architecture. Only references down the stack (DECT, TCP, …) • iadd is a good well behaved byte code • idiv is not quite so well behaved – requires the presence of java.lang.ArithmeticException • invokedynamic is not well behaved – requires the presence of a multitude of API classes • Dependencies are up the stack – not down