pinpoint-apm/pinpoint · error · RuntimeException

{} define fail cl:{} Caused by:{}

Error message

{} define fail cl:{} Caused by:{}

What it means

Thrown by UnsafeDefineClass.handleDefineClassFail when defining a transformed class via sun.misc.Unsafe.defineClass fails. The underlying error (wrapped as ReflectiveOperationException, typically caused by ClassFormatError or LinkageError) is wrapped in a RuntimeException with the class name, classloader, and cause message. Functionally identical to the reflection-based define failure but on the Unsafe code path.

Source

Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/classloading/UnsafeDefineClass.java:69

    @Override
    public Class<?> defineClass(ClassLoader classLoader, String name, byte[] bytes) {
        if (logger.isDebugEnabled()) {
            logger.debug("define class:{} cl:{}", name, classLoader);
        }
        try {
            return (Class<?>) DEFINE_CLASS.invoke(UNSAFE, name, bytes, 0, bytes.length, classLoader, null);
        } catch (InvocationTargetException e) {
            // unwrap: the message of the LinkageError/ClassFormatError thrown by the VM is on the cause
            final Throwable cause = e.getCause() != null ? e.getCause() : e;
            throw handleDefineClassFail(classLoader, name, cause);
        } catch (ReflectiveOperationException e) {
            throw handleDefineClassFail(classLoader, name, e);
        }
    }

    private RuntimeException handleDefineClassFail(ClassLoader classLoader, String className, Throwable cause) {
        logger.warn("{} define fail cl:{} Caused by:{}", className, classLoader, cause.getMessage(), cause);
        return new RuntimeException(className + " define fail Caused by:" + cause.getMessage(), cause);
    }
}

View on GitHub (pinned to 744c3d3075)

Solutions

  1. Check the 'Caused by' for the actual LinkageError/ClassFormatError
  2. Confirm the JDK supports the Unsafe path; on JDK 17+ add required --add-opens flags or upgrade Pinpoint which uses Lookup-based defines
  3. Check for duplicate transformation of the same class in the same classloader
  4. Exclude the problematic class or upgrade the agent for a bytecode fix

Example fix

// before
throw handleDefineClassFail(classLoader, name, e);
// after
if (e.getCause() instanceof LinkageError) {
    logger.warn("class {} already defined or incompatible in cl:{}", name, classLoader, e);
}
throw handleDefineClassFail(classLoader, name, e);
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the JDK still exposes sun.misc.Unsafe define support before relying on this path
try {
    Class.forName("sun.misc.Unsafe");
} catch (ClassNotFoundException e) {
    // Unsafe unavailable; expect UnsafeDefineClass to fail, use alternative agent version
}

Try / catch

try {
    agent.start(...);
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().contains("define fail")) {
        logger.warn("Unsafe define failed; check Caused by for LinkageError", e);
    } else { throw e; }
}

Prevention

When it happens

Trigger: UnsafeDefineClass.defineClass is invoked during instrumentation and the Unsafe-based define throws - e.g. invalid/incompatible bytecode, duplicate class in same classloader, missing referenced classes, or sun.misc.Unsafe unavailable/restricted (JDK 17+ encapsulation).

Common situations: Newer JDKs restrict sun.misc.Unsafe access; bytecode transformation bug; class defined twice in one loader; class file version newer than the JVM; missing dependency class at define time.

Related errors


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