Mastering Java MethodHandle: From Lookup to Performance Benchmarks
This article provides a comprehensive guide to Java MethodHandle, covering its differences from reflection, step‑by‑step creation (Lookup, MethodType, finding handles, invocation), advanced techniques like binding and dropping arguments, array spreading, and a JMH performance comparison with reflection, all demonstrated in a Spring Boot 3.4.2 environment.
Introduction
Java reflection and MethodHandle both enable runtime method manipulation, but they differ in design goals and performance characteristics.
Practical Example Overview
The guide demonstrates creating and using a MethodHandle in four steps: creating a Lookup object, defining a MethodType, locating the method handle, and invoking it.
1. Create Lookup
Use MethodHandles.publicLookup() for public access or MethodHandles.lookup() for private/protected access.
MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();
MethodHandles.Lookup lookup = MethodHandles.lookup();2. Create MethodType
MethodType describes the return type and parameter types of the target method.
MethodType mtBigDecimal = MethodType.methodType(BigDecimal.class, double.class);
MethodType mtVoid = MethodType.methodType(void.class, String.class);
MethodType mtString = MethodType.methodType(String.class, char.class, char.class);
MethodType mtList = MethodType.methodType(List.class, Object[].class);
MethodType mtBool = MethodType.methodType(boolean.class, Book.class);3. Find MethodHandle
Examples for virtual, static, constructor, and private methods.
// virtual method
MethodHandle concatMH = lookup.findVirtual(String.class, "concat", mtString);
// static method
MethodHandle asListMH = lookup.findStatic(Arrays.class, "asList", mtList);
// constructor
MethodHandle newStringMH = lookup.findConstructor(String.class, mtVoid);
// private method via reflection
Method calcDiscountMethod = Book.class.getDeclaredMethod("calcDiscount", double.class);
calcDiscountMethod.setAccessible(true);
MethodHandle calcDiscountMH = lookup.unreflect(calcDiscountMethod);4. Invoke MethodHandle
Three invocation styles are shown:
invoke – strict, requires exact argument count and performs necessary conversions.
invokeWithArguments – flexible, accepts a variable‑length argument list.
invokeExact – most strict, no conversions allowed.
// invoke example
String result = (String) concatMH.invoke("pacg", Character.valueOf('g'), 'k');
// invokeWithArguments example
Object discount = calcDiscountMH.invokeWithArguments(book, 0.55);
// invokeExact example
BigDecimal exact = (BigDecimal) calcDiscountMH.invokeExact(book, 0.55);Array Argument Spreading
Use asSpreader to adapt a handle to accept an array instead of fixed arguments.
MethodHandle isPriceEqualMH = lookup.findVirtual(Book.class, "isPriceEqual", mtBool);
isPriceEqualMH = isPriceEqualMH.asSpreader(Book[].class, 1);
boolean equal = (boolean) isPriceEqualMH.invokeExact(book1, new Book[]{book2});Enhancing MethodHandle
Bind arguments to preset values, creating a new handle that requires fewer parameters.
MethodHandle bound = concatMH.bindTo("pack_");
System.err.println(bound.invoke("xg"));Dropping Arguments
Use MethodHandles.dropArguments to ignore extra parameters when the method signature expects fewer.
MethodHandle concatMH = lookup.findStatic(MethodHanldeDropArgumentDemo.class, "concat", mtString);
concatMH = MethodHandles.dropArguments(concatMH, 1, String.class);
String out = (String) concatMH.invokeExact("pack", "xg");Performance Comparison
JMH benchmarks compare MethodHandle invocation styles with traditional reflection.
Benchmark Mode Cnt Score Error Units
MethodHandleReflectTest.testMethodHandleInvoke avgt 5 53.055 ±0.621 ns/op
MethodHandleReflectTest.testMethodHandleInvokeExact avgt 5 55.394 ±0.514 ns/op
MethodHandleReflectTest.testMethodHandleInvokeWithArguments avgt 5 156.647 ±2.313 ns/op
MethodHandleReflectTest.testReflect avgt 5 56.372 ±0.653 ns/opSpring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
