pinpoint-apm/pinpoint · error · RuntimeException

${className} define fail Caused by:${causeMessage}

Error message

${className} define fail Caused by:${causeMessage}

What it means

UnsafeDefineClass.defineClass uses sun.misc.Unsafe.defineClass to inject bytecode. As in ReflectionDefineClass, when the VM rejects the class or the Unsafe invocation fails, handleDefineClassFail throws RuntimeException '<className> define fail Caused by:<causeMessage>'.

Source

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

            UNSAFE = theUnsafe.get(null);
            DEFINE_CLASS = unsafeClass.getMethod("defineClass",
                    String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class);
        } catch (ReflectiveOperationException e) {
            throw new IllegalStateException("Cannot access sun.misc.Unsafe.defineClass", e);
        }
    }

    @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. Read the cause message for the VM-level reason and fix the offending transformer.
  2. Switch instrument classloading mode in Pinpoint config (e.g. to reflection/ASMFallback) if Unsafe is unavailable.
  3. Exclude the failing class from instrumentation.
  4. Upgrade the agent to a build supporting the running JDK.

Example fix

// before
return (Class<?>) DEFINE_CLASS.invoke(UNSAFE, name, bytes, 0, bytes.length, classLoader, null);
// after (guard availability)
if (!UNSAFE_SUPPORTED) {
    return reflectionDefineClass.defineClass(classLoader, name, bytes);
}
Defensive patterns

Strategy: fallback

Validate before calling

// check Unsafe availability at agent init
boolean unsafeOk;
try {
    Class<?> u = Class.forName("sun.misc.Unsafe");
    unsafeOk = u.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class, ClassLoader.class, java.security.ProtectionDomain.class) != null;
} catch (ReflectiveOperationException e) {
    unsafeOk = false;
}

Try / catch

try {
    return unsafeDefineClass.defineClass(classLoader, name, bytes);
} catch (RuntimeException e) {
    logger.warn("Unsafe define failed for {} ({}), falling back", name, e.getCause());
    return reflectionDefineClass.defineClass(classLoader, name, bytes);
}

Prevention

When it happens

Trigger: DEFINE_CLASS.invoke(UNSAFE, name, bytes, 0, bytes.length, classLoader, null) throws InvocationTargetException (VM rejected the class: ClassFormatError/LinkageError/duplicate define) or ReflectiveOperationException (Unsafe API missing/changed).

Common situations: Invalid transformed bytecode from a plugin; class already defined by the target loader; newer JDKs restricting/removing sun.misc.Unsafe.defineClass (JDK 11+ deprecation, removal paths); agent-JVM version mismatch.

Related errors


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