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
- Check the 'Caused by' for the actual LinkageError/ClassFormatError
- Confirm the JDK supports the Unsafe path; on JDK 17+ add required --add-opens flags or upgrade Pinpoint which uses Lookup-based defines
- Check for duplicate transformation of the same class in the same classloader
- 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
- On JDK 17+, ensure required --add-opens flags or use an agent version using Lookup.defineClass
- Avoid duplicate class transformation in the same classloader
- Confirm instrumented bytecode version is <= target JVM version
- Inspect the 'Caused by' before changing any config
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
- {} define fail cl:{} Caused by:{}
- ${name} define fail Caused by:${e.getMessage()}
- Target class is not modifiable
- {} define fail cl:{} Caused by:{}
- ${className} define fail Caused by:${causeMessage}
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/6ee18b266100488d.
Report an issue: GitHub.