Working with Method Handles

1. Understanding MethodHandle API

ConceptDetail
Classjava.lang.invoke.MethodHandle
Created byMethodHandles.Lookup
TypedCarries MethodType
Backed byinvokedynamic infrastructure

2. Creating MethodHandles

LookupFor
findVirtualInstance method
findStaticStatic method
findConstructorConstructor
findGetter / findSetterField
findSpecialsuper-call

3. Invoking MethodHandles

MethodType Check
invokeExact(args)Strict — exact type match
invoke(args)Adapts via casts/conversions
invokeWithArguments(Object...)Reflective-style
Warning: invokeExact requires the call site descriptor to match exactly — a return type or arg mismatch throws WrongMethodTypeException.

4. Using Method Types (MethodType)

FactoryResult
methodType(rt)No params
methodType(rt, p1, p2)With params
methodType(rt, paramsList)From list
changeReturnType / appendParameterTypesMutate

5. Binding Methods (bindTo)

AdapterEffect
bindTo(receiver)Curry first arg
insertArguments(pos, vals)Insert constant args
dropArguments(pos, types)Ignore extra args
asType(MethodType)Cast/convert
asSpreader / asCollectorArray spread

6. Creating Dynamic Call Sites

TypeUse
ConstantCallSiteFixed target
MutableCallSiteReassignable
VolatileCallSiteThread-safe reassign

7. Understanding invokedynamic Instruction

invokedynamic
  → bootstrap method (one-time)
  → returns CallSite (with MethodHandle target)
  → subsequent calls go directly to target
      
UseExample
Lambda creationLambdaMetafactory
String concatStringConcatFactory (Java 9+)
Switch on patternsJava 21+

8. Comparing MethodHandle vs Reflection

FeatureReflectionMethodHandle
SpeedSlow (boxing, checks)Near direct call
Access checkPer callAt lookup only
Type safetyObject[]MethodType-checked
JIT optimizationLimitedInlined when constant

9. Using MethodHandles for Performance

PatternTrick
Static finalAllows JIT constant folding
invokeExactAvoids type adaptation
LambdaMetafactoryBuild typed FI implementations
Hot pathCache MethodHandle in static field

Example: Generated FI

MethodHandles.Lookup lk = MethodHandles.lookup();
MethodHandle target = lk.findVirtual(String.class, "length", MethodType.methodType(int.class));
CallSite site = LambdaMetafactory.metafactory(lk, "applyAsInt",
    MethodType.methodType(ToIntFunction.class),
    MethodType.methodType(int.class, Object.class),
    target,
    MethodType.methodType(int.class, String.class));
ToIntFunction<String> f = (ToIntFunction<String>) site.getTarget().invokeExact();

10. Using VarHandle for Field Access

APIUse
MethodHandles.lookup().findVarHandle(cls, "field", T.class)Instance field
findStaticVarHandleStatic field
arrayElementVarHandle(int[].class)Array element
Atomic opscompareAndSet, getAndAdd, getVolatile