baomidou/mybatis-plus · critical · IllegalStateException

There is neither 'privateLookupIn(Class, Lookup)' nor 'Looku

Error message

There is neither 'privateLookupIn(Class, Lookup)' nor 'Lookup(Class, int)' method in java.lang.invoke.MethodHandles.

What it means

In a static initializer, MybatisMapperProxy tries to obtain a method handle factory: first MethodHandles.privateLookupIn (JDK 9+), and on absence falls back to the JDK 8-era MethodHandles.Lookup(Class, int) constructor. If neither is retrievable, the class cannot initialize and throws IllegalStateException. This is a JVM-compatibility failure, not an application logic error.

Source

Thrown at mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/override/MybatisMapperProxy.java:77

    }

    static {
        Method privateLookupIn;
        try {
            privateLookupIn = MethodHandles.class.getMethod("privateLookupIn", Class.class, MethodHandles.Lookup.class);
        } catch (NoSuchMethodException e) {
            privateLookupIn = null;
        }
        privateLookupInMethod = privateLookupIn;

        Constructor<MethodHandles.Lookup> lookup = null;
        if (privateLookupInMethod == null) {
            // JDK 1.8
            try {
                lookup = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
                lookup.setAccessible(true);
            } catch (NoSuchMethodException e) {
                throw new IllegalStateException(
                    "There is neither 'privateLookupIn(Class, Lookup)' nor 'Lookup(Class, int)' method in java.lang.invoke.MethodHandles.",
                    e);
            } catch (Exception e) {
                lookup = null;
            }
        }
        lookupConstructor = lookup;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            if (Object.class.equals(method.getDeclaringClass())) {
                return method.invoke(this, args);
            }
            return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
        } catch (Throwable t) {
            throw ExceptionUtil.unwrapThrowable(t);

View on GitHub (pinned to bf67d90747)

Solutions

  1. Run on a standard JDK 8+ distribution (JDK 11/17 recommended) where privateLookupIn exists
  2. For GraalVM/native-image, register MethodHandles.Lookup for reflection in reflect-config / RuntimeReflection
  3. Upgrade mybatis-plus to a version matching your JVM; newer releases handle modern JDK encapsulation
  4. For Android, use a JVM-compatible runtime or a mybatis alternative designed for Android

Example fix

# before: runtime lacks Lookup(Class,int) and privateLookupIn
java --add-opens java.base/java.lang=ALL-UNNAMED -jar app.jar  # still fails if ctor filtered
# after: use standard JDK 17 where privateLookupIn is present
java -jar app.jar  # requires JDK 9+
Defensive patterns

Strategy: fallback

Validate before calling

// At startup, verify the JVM can satisfy mapper proxy method-handle setup
try {
    MethodHandles.Lookup lookup = (MethodHandles.Lookup) MethodHandles.class
        .getMethod("privateLookupIn", Class.class, MethodHandles.Lookup.class)
        .invoke(null, MybatisMapperProxy.class, MethodHandles.lookup());
} catch (NoSuchMethodException e) {
    // verify JDK8 fallback constructor exists
    MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
}

Try / catch

catch ExceptionInInitializerError / IllegalStateException from first mapper use; report 'unsupported runtime' to ops — no in-process retry or fallback is possible after class-init failure.

Prevention

When it happens

Trigger: Running on a non-standard or stripped JVM/runtime where both privateLookupIn is missing and the Lookup(Class,int) constructor is absent or inaccessible (some Android runtimes, restricted JVM forks, or module-lockdown setups removing the constructor via reflection filters).

Common situations: Deploying mybatis-plus on Android/GraalVM native images with incomplete reflection metadata; JDK builds with strong encapsulation filters (e.g. --illegal-access=deny era / later JDKs where the private constructor is filtered); ahead-of-time compilation stripping the constructor.

Related errors


AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14). Data as JSON: /api/errors/f562484395637fe2. Report an issue: GitHub.