pinpoint-apm/pinpoint · error · IllegalArgumentException

unexpected class ${className}

Error message

unexpected class ${className}

What it means

LambdaFactoryClassAdaptor.transform rewrites the bytecode of a JVM lambda factory synthetic class, expecting the class it reads to be exactly LAMBDA_FACTORY_CLASS_NAME (java/lang/invoke/LambdaMetafactory-style). If the replaced class name differs, it throws IllegalArgumentException because the adaptor was applied to the wrong class. It also warns when the method-instruction replacement count is not exactly 1.

Source

Thrown at agent-module/profiler-optional/profiler-optional-jdk8/src/main/java/com/navercorp/pinpoint/profiler/instrument/lambda/LambdaFactoryClassAdaptor.java:68

            return new LambdaClassJava15();
        } else if (JvmUtils.getVersion().onOrAfter(JvmVersion.JAVA_9)) {
            return new LambdaClassJava9();
        } else {
            return new LambdaClassJava8();
        }
    }

    public byte[] transform(byte[] bytes, LambdaClass lambdaClass) {
        Objects.requireNonNull(bytes, "bytes");

        final ClassReader reader = new ClassReader(bytes);
        final ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
        final List<MethodInsn> methodInsnList = lambdaClass.getMethodInsnList();
        final MethodInstReplacer methodInstReplacer = new MethodInstReplacer(writer, methodInsnList);
        reader.accept(methodInstReplacer, 0);

        if (!LAMBDA_FACTORY_CLASS_NAME.equals(methodInstReplacer.getClassName())) {
            throw new IllegalArgumentException("unexpected class " + methodInstReplacer.getClassName());
        }

        if (methodInstReplacer.getTransformCount() != 1) {
            logger.warn("unexpected {} invoke count {}", methodInsnList, methodInstReplacer.getTransformCount());
            // dump bytecode
        }
        return writer.toByteArray();
    }
}

View on GitHub (pinned to 744c3d3075)

Solutions

  1. Verify the transformer's matcher targets the exact lambda factory class name for the running JDK
  2. Update the plugin/profiler-optional-jdk8 module to a version compatible with the current JDK's lambda naming
  3. Narrow the transform matcher so only the intended synthetic lambda class is adapted
  4. Check the logged actual class name in the message and adjust LAMBDA_FACTORY_CLASS_NAME accordingly

Example fix

// before
if (!LAMBDA_FACTORY_CLASS_NAME.equals(methodInstReplacer.getClassName())) {
    throw new IllegalArgumentException("unexpected class " + methodInstReplacer.getClassName());
}
// after
String actual = methodInstReplacer.getClassName();
if (!LAMBDA_FACTORY_CLASS_NAME.equals(actual) && !ALT_LAMBDA_FACTORY_CLASS_NAME.equals(actual)) {
    logger.warn("skipping transform, unexpected class {}", actual);
    return null; // leave bytecode untouched instead of failing the transform
}
Defensive patterns

Strategy: try-catch

Validate before calling

byte[] transformed;
try {
    transformed = adaptor.transform(loader, className, clazz, protectionDomain, bytecode);
} catch (Exception e) {
    logger.warn("lambda transform skipped for {}", className, e);
    return null; // return original bytecode
}

Try / catch

try {
    return loadTransformedBytecode(lambdaClass);
} catch (IllegalArgumentException e) {
    logger.warn("unexpected class during lambda transform: {}", e.getMessage());
    return originalBytecode; // degrade gracefully instead of failing class loading
}

Prevention

When it happens

Trigger: ClassFileTransformer/loadTransformedBytecode matched a class name pattern that resolved to a different runtime class name than the expected lambda factory class (e.g. a lambda subclass or a differently named synthetic class under the same matcher).

Common situations: JDK updates changing lambda synthetic class naming; lambda proxy classes cached/reused across classloaders; overly broad transform matcher matching a non-lambda class.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07). Data as JSON: /api/errors/244b9c99ad1b6336. Report an issue: GitHub.