pinpoint-apm/pinpoint · error · InstrumentException
not found InterceptorHolderClass, className=
Error message
not found InterceptorHolderClass, className=
What it means
loadClass resolves the generated holder class name (com.navercorp.pinpoint.profiler.instrument.interceptor.InterceptorHolder$$N) via Class.forName(className, false, classLoader). This InstrumentException is thrown when the class is not yet defined in the given classloader — i.e. loadClass was called before defineClass, or the holder was defined into a different classloader.
Source
Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/ASMInterceptorHolder.java:135
private void init(Class<?> interceptorHolderClass, Supplier<Interceptor> supplier) throws InstrumentException {
try {
final Method method = interceptorHolderClass.getDeclaredMethod("set", Supplier.class);
method.invoke(null, supplier);
} catch (NoSuchMethodException e) {
throw new InstrumentException("not found 'set' method, className=" + interceptorHolderClass.getName(), e);
} catch (IllegalAccessException e) {
throw new InstrumentException("access fail, className=" + interceptorHolderClass.getName(), e);
} catch (InvocationTargetException e) {
throw new InstrumentException("invocation fail, className=" + interceptorHolderClass.getName(), e);
}
}
public Class<?> loadClass(ClassLoader classLoader) throws InstrumentException {
try {
return Class.forName(className, false, classLoader);
} catch (ClassNotFoundException e) {
throw new InstrumentException("not found InterceptorHolderClass, className=" + className);
}
}
public Class<?> defineClass(ClassLoader classLoader) throws InstrumentException {
try {
final byte[] mainClassBytes = toMainClassByteArray();
final Class<?> mainClass = InterceptorDefineClassHelper.defineClass(classLoader, className, mainClassBytes);
final byte[] innerClassByte = toInnerClassByteArray();
InterceptorDefineClassHelper.defineClass(classLoader, innerClassName, innerClassByte);
return mainClass;
} catch (Exception e) {
throw new InstrumentException("defineClass fail", e);
}
}
byte[] toMainClassByteArray() throws InstrumentException {
try {
ClassNode classNode = readClass(INTERCEPTOR_HOLDER_CLASS);View on GitHub (pinned to 744c3d3075)
Solutions
- Call defineClass(classLoader) (or Builder.build()) before loadClass/loadInterceptorClass with the same ClassLoader instance
- Ensure the same classloader used at define time is passed at load time — null maps to the bootstrap loader
- Verify the agent's transformer pipeline initializes the holder before any code path reads it
- Log holder class name and classloader identity on both define and load to spot mismatches
Example fix
// before ASMInterceptorHolder holder = new ASMInterceptorHolder(id); Class<? extends Interceptor> c = holder.loadInterceptorClass(appClassLoader); // not defined yet // after holder.defineClass(appClassLoader); Class<? extends Interceptor> c = holder.loadInterceptorClass(appClassLoader);
Defensive patterns
Strategy: validation
Validate before calling
// call defineClass/build first, then load with the same loader holder.defineClass(appClassLoader); Class<?> check = Class.forName(holder.getClassName(), false, appClassLoader); // must not throw
Try / catch
try {
Class<?> c = holder.loadClass(appClassLoader);
} catch (InstrumentException e) {
logger.error("holder {} not defined in this classloader; call defineClass first", holder.getClassName());
} Prevention
- Establish a strict order: create -> defineClass/build -> loadClass/init
- Use the identical ClassLoader instance for define and load (null = bootstrap)
- Never look up holder classes by name in classloaders that never had them defined
When it happens
Trigger: Calling loadInterceptorClass(classLoader) (which calls loadClass) without first calling defineClass for that classloader; or defining the holder into the bootstrap loader (classLoader==null path) but later loading it through an application classloader (or vice versa).
Common situations: Custom instrumentation code that builds the holder in one classloader and reads it from another; ordering bugs where loadInterceptorClass runs before Builder.build(); agent restart/shadow classloader mismatches.
Related errors
- not found class
- not found Caused by:
- not BootStrapClassLoader
- unknown scanner type classLoader:${classLoader} protectionDo
- Transformer already exists. TransformKey:
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/6a3803781b34ba74.
Report an issue: GitHub.