2. So what are we going to talk about?
●
What are method handles?
●
How are method handles related to reflection?
●
What is invokedynamic about?
●
●
●
●
How are method handles used with
invokedynamic?
What are lambda expressions?
How are method handles used with lambda
expressions?
What are a few other interesting things coming
in Java 8?
3. What is a method handle?
●
●
●
A reference to a method (or field, constructor or
other bit of functionality) that can be executed
Defined in package java.util.invoke
Introduced with invokedynamic support (JSR
292) in Java 7
4. How is a method handle obtained?
●
●
Every method has a type that is described by a
MethodType instance
MethodHandle instances are obtained using a
MethodHandles.Lookup factory that knows
about methods that are available in the current
context
5. The MethodType Class
●
●
●
●
Used to describe the parameters and return type of a
method handle
All instances are immutable
Instances are created using the
MethodType.methodType factory method
Examples
●
●
●
MethodType.methodType(BigDecimal.class, int.class)–
(I)Ljava/math/BigDecimal;
MethodType.methodType(String.class) ()Ljava/lang/String;
MethodType.methodType(boolean.class, String.class) (Ljava/lang/String;)Z;
6. The MethodHandles.Lookup
Class
●
●
●
●
Factory for creating method handles
Created using MethodHandles.lookup
method
Knows about all methods that are accessible
from the calling context
Method handles are obtained from the factory
using the find methods which include:
●
findVirtual – instance methods
●
findConstructor - constructors
●
findStatic – class methods
7. How is a method handle obtained?
(continued...)
●
●
●
●
Obtain a lookup context
Create a MethodType that describes the return type
and parameters of the method
Get a MethodHandle instance representing the
method using the appropriate find method
Example
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType mt = MethodType.methodType(BigDecimal.class,
int.class)
MethodHandle power =
lookup.findVirtual(BigDecimal.class, "pow", mt);
8. How is a method handle invoked?
●
Invoked using one of the MethodHandle invoke
methods
●
●
invokeExact – types of arguments must exactly
match the parameter types
invoke – transformations will be performed on
arguments prior to invocation attempt (e.g. boxing,
unboxing, widening)
9. Method Handle Invocation
Examples
// Obtain a lookup context
MethodHandles.Lookup lookup = MethodHandles.lookup();
// Construct the method type
MethodType mt = MethodType.methodType(BigDecimal.class, int.class);
// Obtain the method handle
MethodHandle power = lookup.findVirtual(BigDecimal.class, "pow", mt);
// Invoke the method
BigDecimal p = (BigDecimal)power.invoke(new BigDecimal(5), 2);
p = (BigDecimal)power.invoke(new BigDecimal(5), (byte)2);
p = (BigDecimal)power.invoke(new BigDecimal(5), new Integer(2));
p = (BigDecimal)power.invokeExact(new BigDecimal(5), 2);
// These don't work because arguments or return type don't match
//p = (BigDecimal)power.invokeExact(new BigDecimal(5), (byte)2);
//p = (BigDecimal)power.invokeExact(new BigDecimal(5), new Integer(2));
//Object o = power.invokeExact(new BigDecimal(5), 2);
10. How are method handles related to
reflection?
●
●
●
●
Convert from Method instance to MethodHandle
instance using
MethodHandles.Lookup.unreflect method
Method handles more efficient because access at
lookup time rather than at invocation time
Method handle API requires pretty specific knowledge
of signature to obtain a method handle, unlike
reflection
At the end of the day, method handles are the future of
introspection
11. Method Handle API FunctionalFlavored Features
●
●
MethodHandles class provides methods that can
construct method handles from other method handles
Examples
●
dropArguments – remove arguments
●
filterArguments – pre-process arguments, filter for each
●
filterReturnValue – post-process return value
●
foldArguments – pre-process arguments, apply combiner
●
guardWithTest – applies test to determine invocation
●
insertArguments – binds argument values
●
permuteArguments – reorders arguments
12. Example – insertArgument
MethodHandle insertArguments(MethodHandle
target, int pos, Object... values)
MethodHandle square =
MethodHandles.insertArguments(power, 1, 2);
System.out.println(square.invoke(new BigDecimal(5)));
●
Like currying,where parameters are bound resulting in
a new method
13. What is invokedynamic support?
●
●
●
●
Introduced in Java 7 to support dynamic method
invocation
Primarily for dynamic language designers that create
Java bytecode, not Java programmers
Currently not used by Java compiler, but will be in
Java 8 with lambda expressions
Consists of a new invokedynamic bytecode and the
means for determining at runtime what functionality
should be executed when a method is invoked
14. How is a method invoked using
invokdynamic?
●
●
●
invokedynamic bytecode instruction writing
to class file when method is dynamic invoked
Argument to invokedynamic instruction is a
reference to a bootstrap method that has been
written to a special place in the class file
Bootstrap method creates a CallSite
instance that can be used at runtime to execute
appropriate method
15. What is a CallSite?
●
●
●
●
Where method handles come into play with
invokedynamic support
CallSite instance created by the bootstrap method
that is associated with the invokedynamic
instruction
CallSite instance holds a method handle reference
(the target) which is invoked by the JVM at runtime
At runtime when the JVM encounters an
invokedynamic instruction, it invokes the
MethodHandle target associated with the CallSite
instance
17. What is a lambda expression?
●
●
●
●
●
Introduced in Java 8 – JSR 335
Represents a block of functionality that can be
executed and referenced
Anonymous method
Similar to a closure in other languages, but only allows
reference to effectively final (variables declared final or
not reassigned) from surrounding scope
Treated by the runtime as an instance of a special
type of interface called a functional interface
18. How is a lambda expression
defined?
●
Syntax is: <parameter list> -> <body>
●
Parameters are optionally typed
●
●
●
●
●
If type omitted it will be inferred by the compiler from
the declaration context
Parameter list must be surrounded by parentheses if
more than one parameter or explicitly typed
Body is a single expression or a block of statements
Single expression doesn't require braces or an explicit
return
Return required if braces used for body
19. Lambda Expression Examples
() -> System.out.println(“Hello!”)
n -> n > 5
(int n) -> n > 5
(n) -> {return n > 5;}
(a,b) -> Integer.compare(a,b)
(a,b) -> {return Integer.compare(a,b);}
20. What is the type of a lambda
expression?
●
●
●
●
Lamba expressions are like regular Java expressions
and have a type
Their type is inferred from the surrounding context by
the compiler, called the target type
Lambda expressions can only appear in context where
target type is a functional interface
So lambda expressions are represented at runtime by
functional interfaces
21. What is a functional interface?
●
Interface with a single abstract method
●
Runnable and Comparator are examples
●
●
Package java.util.function contains over
40 functional interfaces
Examples from this package include:
●
●
Consumer<T> - accepts single input argument and
returns no result
Predicate<T> - accepts single input argument and
returns boolean result
22. Lambda expressions and target type
●
●
Lambda expressions are implemented using
the functional interface target type to infer
parameter types and the return type of the
lambda expression
This is why lambda expressions don't require
explicitly typed parameters or a return type,
they can be inferred from target type by the
compiler
23. Target Type Examples
IntPredicate p = n -> n > 5;
p.test(4);
Comparator c =(a,b) ->
Integer.compare(a,b);
c.compare(1,2);
Runnable r = () ->
System.out.println(“Hello!”)
r.run();
24. How are lambda expressions
implemented?
●
●
●
●
invokedynamic is used to allow flexibility of
lambda expression implementation
Allows selection of translation strategy to be
deferred until runtime
When compiler encounters lambda expression,
lambda is 'desugared' into a private static
method whose parameter types and return type
match that of the functional target type
This method is called by the instance of the
functional target type that is generated by the
invokedynamic instruction
25. 'Desugaring' Example
IntPredicate p = n -> n > 5;
IntPredicate has one method, test that takes an int
argument and returns a boolean
Compiler creates private static method within the class that
contains the lambda expression
private static boolean lambda$0(int n) {
return n > 5;
}
Method parameters and return type determined from
IntPredicate.test method parameters and return
type
26. The lambda invokedyanmic
instruction
●
●
●
The compiler generates an invokedynamic
instruction at the point in the code where the
lambda expression appears
When invoked, the instruction returns an
instance of the functional interface
Dynamic arguments to invokedynamic
instruction (those passed to bootstrap method)
are values captured from lexical scope
27. The lambda bootstrap method
●
●
Bootstrap method associated with the generated
invokedynamic instruction is the method
LambdaMethodFactory.metafactory
Takes information about target type and the lambda
implementation (desugared) method and generates a
CallSite instance that is linked to the
invokedynamic instruction
28. The generated CallSite instance
●
●
CallSite generated by the bootstrap
method has an associated MethodHandle
target that when invoked returns an instance
of the functional interface target type
associated with the lambda expression
The single method of the returned instance
calls the 'desugared' generated method
29. To summarize at compile-time...
●
●
●
●
●
Compiler encounters lambda expression
Compiler determines functional interface
target type from context
Compiler generates desugared lambda
method
Compiler indicates bootstrap method and
provides static arguments about lambda
known at compile-time (target type, method
handle for desugared lambda, etc.)
Compiler generates invokedynamic
instruction referencing bootstrap method
30. Some javap output
import java.util.function.*;
public class Lambda1 {
public static void main(String[] args) {
IntPredicate p = n -> n > 5;
}
}
31. How are lambda expressions used?
●
Often used in conjunction with collections and
iterators
●
Also used with event listeners for callbacks
●
Examples
List<Integer> list = Arrays.asList(1,5,4,3,7);
Collections.sort(list,
(a,b) -> Integer.compare(a,b));
list.forEach(n -> System.out.println(n));
32. A Few Additional Java 8 Features
●
Method references
●
●
●
●
Allows a method to be used like a lambda expression
Lambdas define the function body, method references
refer to an existing method by name
Kind of like shorthand for a lambda expression that just
invokes the named method with the lambda arguments
Kinds of method references
–
–
–
Static method (className::methodName)
Instance method (instanceRef::methodName)
Constructor (className::new)
34. A Few Additional Java 8 Features
(cont.)
●
Default interface methods
●
Allow interfaces to evolve
●
Concrete behavior that is added to an interface
●
Methods of interface are either default or abstract
●
●
●
Default methods have an implementation that is
inherited by implementing classes
Don't count towards 'one abstract method' rule of
functional interfaces
Can be overridden
36. A Few Additional Java 8 Features
(cont.)
●
Static interface methods
●
●
Allow helper methods to live in interface
Example
– Comparator<T>
●
<T extends Comparable<? super T>>
Comparator<T> reverseOrder()
37. Take Aways
●
●
●
●
●
Method handles offer a more modern and efficient
alternative to reflection for method invocation, particularly if
you know what you are looking for
invokedynamic is intended for applications that generate
bytecode, not typical Java language user
Lambda expressions offer a concise, convenient way to
define an anonymous methods and are treated like any
other expression in Java
Many existing library classes have been modified to offer
lambda support
Interfaces can now have behavior associated with them
38. Wrapping up...
●
●
●
●
Encouraging innovation
Indicates Java language designers want the
language to stay relevant
When evaluating Java language enhancements
keep in mind they are working within the
confines of a widely-adopted language
A given offering may not be as robust as that in
other languages, but they don't have the
freedom to make changes that aren't backwardcompatible
39. References
●
Method Handles and invokedynamic
●
●
●
The Well Grounded Java Developer – Manning
Java Virtual Machine Specification
http://docs.oracle.com/javase/specs/jvms/se7/html/index.html
Lambda Expressions
●
Open JDK Project Lambda (http://openjdk.java.net/projects/lambda/)
●
Java 8 Early Access Documentation (http://download.java.net/jdk8/docs)
●
Brian Goetz documents
–
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html
–
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-libraries-final.html
–
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html