Method Handles in Java


Published on

Detroit JUG presentation 11/6/2013. Covers method handles, invokedynamic and lambda expressions.

Published in: Technology, Education
1 Comment
  • very useful and well explained presentation
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Method Handles in Java

  1. 1. Method Handles in Java and some neat Java 8 stuff too!
  2. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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
  16. 16. Runtime dynamic method invocation
  17. 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. 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. 19. Lambda Expression Examples () -> System.out.println(“Hello!”) n -> n > 5 (int n) -> n > 5 (n) -> {return n > 5;} (a,b) ->,b) (a,b) -> {return,b);}
  20. 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. 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. 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. 23. Target Type Examples IntPredicate p = n -> n > 5; p.test(4); Comparator c =(a,b) ->,b);,2); Runnable r = () -> System.out.println(“Hello!”);
  24. 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. 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. 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. 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. 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. 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. 30. Some javap output import java.util.function.*; public class Lambda1 { public static void main(String[] args) { IntPredicate p = n -> n > 5; } }
  31. 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) ->,b)); list.forEach(n -> System.out.println(n));
  32. 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)
  33. 33. Method Reference Examples // static method reference Function<Integer,String> hexMe = Integer::toHexString; hexMe.apply(10); // instance method reference String s = "Test it"; Predicate<String> m = s::startsWith; m.test("T");
  34. 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
  35. 35. Default Method Examples ● Iterable<E> ● ● forEach(Consumer<? super T> action) Comparator<T> ● Comparator<T> reversed()
  36. 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. 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. 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. 39. References ● Method Handles and invokedynamic ● ● ● The Well Grounded Java Developer – Manning Java Virtual Machine Specification Lambda Expressions ● Open JDK Project Lambda ( ● Java 8 Early Access Documentation ( ● Brian Goetz documents – – –