skip to content

MethodHandles

MethodHandles from java.lang.invoke perform their access check once at lookup time and then invoke with near-direct-call speed, unlike reflection which checks on every call. Interviewers ask how they differ from reflection, and invokeExact versus invoke is the follow-up.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

What is a MethodHandle in java.lang.invoke, and how do you obtain one via MethodHandles.lookup()?

level: middleimportance: should knowfreq 45%

answer

  1. Typed function pointer to a method/ctor/field
  2. Lookup = factory + access context
  3. findVirtual/findStatic/findConstructor
  4. MethodType = signature, no name
  5. Access checked at lookup, not invoke

basics

~20 s

A MethodHandle is a typed, directly-callable reference to a method, constructor, or field. You first get a Lookup object from MethodHandles.lookup(), then ask it to find the method (e.g. findVirtual) and get back a handle you can invoke.

solid answer

~40 s

A MethodHandle (java.lang.invoke) is a strongly-typed, low-level reference to an executable member - a method, constructor, or field accessor - that you can invoke directly. To create one you first obtain a Lookup, normally via MethodHandles.lookup(), which is a factory carrying the access rights of the calling class. You then call a finder such as findVirtual, findStatic, findConstructor, findGetter or findSetter, passing the owning class, the member name, and a MethodType describing the signature. The Lookup performs the access check at lookup time (so invocation is fast and unchecked), and returns a MethodHandle whose type() matches that signature. Compared with java.lang.reflect.Method, handles are immutable, type-aware, and the JIT can optimise them aggressively, making them the modern foundation for invokedynamic, lambdas, string concatenation, and var-args adaptation.

go deeper

for a junior

Can state that a MethodHandle is a typed reference to a method and that you get one through MethodHandles.lookup() then a find* call.

for a middle

Knows the finder methods (findVirtual/findStatic/findConstructor), that MethodType describes the signature, and that the receiver becomes a leading arg for virtual handles.

for a senior

Explains that Lookup carries access context, that the access check happens at lookup time enabling cheap invocation, and contrasts it with reflective Method.

for a principal

Frames MethodHandles as the invokedynamic substrate underlying lambdas/string-concat and reasons about when to build dynamic call sites versus codegen.

### The problem MethodHandles solve Before Java 7, the only way to call a method whose identity you only knew at runtime was the **Reflection API** (`java.lang.reflect.Method`). Reflection works but has drawbacks: every `invoke` call re-checks access permissions, arguments are boxed into an `Object[]`, and the JIT (the just-in-time compiler that turns bytecode into machine code) struggles to optimise through it. `java.lang.invoke.MethodHandle`, introduced in Java 7, is the modern, faster alternative. Think of a **MethodHandle as a typed function pointer**: an immutable object that points at one executable member (a method, a constructor, or a field getter/setter) and knows the exact signature of what it points at. ### Key terms, defined - **`MethodHandle`** - the callable reference itself. It has a `type()` of class `MethodType`. - **`MethodType`** - an immutable description of a signature: the return type plus the parameter types, with **no method name**. E.g. `(int,int)->int` is a MethodType. You build one with `MethodType.methodType(returnType, paramTypes...)`. - **`MethodHandles.Lookup`** - a *factory* object that also carries an **access context**: it remembers which class requested it, and therefore what that class is allowed to see (public, private, package members visible from the lookup class). You usually get it by calling `MethodHandles.lookup()` from inside the class that needs the access. - **`MethodHandles`** (plural, the utility class) - holds static factory and combinator methods (`lookup()`, `publicLookup()`, `privateLookupIn(...)`, adapters like `insertArguments`, etc.). ### How you obtain a handle, step by step ```java // 1. Get a Lookup carrying THIS class's access rights MethodHandles.Lookup lookup = MethodHandles.lookup(); // 2. Describe the signature you want (return type first) MethodType mt = MethodType.methodType(String.class, int.class); // String f(int) // 3. Ask the lookup to find the member; access is checked HERE MethodHandle mh = lookup.findVirtual(Integer.class, "toString", MethodType.methodType(String.class)); ``` The finder method you call depends on the kind of member: - `findVirtual(refc, name, type)` - an instance (overridable) method; the receiver becomes a *leading* argument. - `findStatic(refc, name, type)` - a static method. - `findConstructor(refc, type)` - a constructor; the return type of `type` must be `void`, the handle returns a new instance. - `findGetter`/`findSetter` - read/write an instance field; `findStaticGetter`/`findStaticSetter` for static fields. - `findSpecial` - non-virtual (super) invocation. ### The crucial idea: access is checked at lookup time When `findVirtual` returns successfully, the permission check is **already done**. The resulting handle can then be invoked any number of times with no further access checks - this is part of why it is fast. A reflective `Method`, by contrast, can re-check (unless you call `setAccessible(true)`). ### Why use it instead of reflection? 1. **Performance** - the JIT treats a constant MethodHandle almost like a direct call; invocation avoids per-call access checks and (with `invokeExact`) avoids boxing. 2. **Type safety** - the handle knows its `MethodType`; signature mismatches fail loudly. 3. **Composability** - handles can be transformed (bind arguments, change types, filter, fold) into new handles. 4. **It is the runtime substrate for `invokedynamic`** - lambdas, method references, and `String` concatenation all bootstrap through MethodHandles. A junior should know it is "a fast, typed alternative to a reflective Method". A senior should know lookup carries access context and the check happens at lookup time. A principal should reach for it when building dynamic dispatch, bytecode-light frameworks, or `invokedynamic` call sites.

  • What does the receiver object map to for a handle from findVirtual?
    It becomes the first (leading) parameter of the handle's MethodType, so you pass the instance as the first argument when invoking.
  • What is the difference between MethodHandles.lookup() and MethodHandles.publicLookup()?
    lookup() captures the calling class's full access (including its private/package members); publicLookup() can only resolve public members of exported packages and has no privileged context.

saying these in an interview costs you the question

  • Saying MethodType includes the method name (it does not - just return + params)
  • Claiming access is re-checked on every invoke (it is checked once, at lookup)
  • Confusing MethodHandle (the callable) with MethodHandles (the utility class)
  • Thinking lookup() returns something global - it carries the caller's access rights

context

open as a page

What is the difference between MethodHandle.invokeExact() and invoke(), and why does invokeExact often throw WrongMethodTypeException?

level: seniorimportance: should knowfreq 40%

basics

~20 s

invokeExact requires the call's argument and return types to match the handle's signature exactly, with no conversions. invoke is more forgiving: it will box, unbox, widen, or cast as needed. invokeExact throws WrongMethodTypeException when the static types at the call site do not match precisely.

open as a page

How do MethodHandles compare to the classic Reflection API in terms of access checks and performance?

level: seniorimportance: should knowfreq 42%

basics

~20 s

Reflection checks access on each use (unless you call setAccessible), boxes arguments into an Object array, and is hard for the JIT to optimise. A MethodHandle checks access once at lookup time and, especially with invokeExact, is much closer to a direct call, so it usually performs better.

open as a page

How do you describe a method's signature with MethodType, and how does it relate to building and adapting MethodHandles?

level: middleimportance: nice to knowfreq 30%

basics

~20 s

MethodType is an immutable object describing a signature: the return type plus the parameter types, with no name. You pass it to find* methods to say which overload you want, and you can derive new MethodTypes (change a parameter, drop one) to adapt a handle's shape.

open as a page

What is MethodHandles.privateLookupIn and when would you use it for cross-class or cross-module access?

level: principalimportance: nice to knowfreq 22%

basics

~20 s

privateLookupIn lets one class obtain a Lookup with private-level access into another class, so it can build handles for that class's private members. The caller must already be allowed to reach the target (same module, or the target's module has opened the package), making it the module-aware replacement for setAccessible.

open as a page