Skip to main content

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

Was this article helpful?