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

  1. Call defineClass(classLoader) (or Builder.build()) before loadClass/loadInterceptorClass with the same ClassLoader instance
  2. Ensure the same classloader used at define time is passed at load time — null maps to the bootstrap loader
  3. Verify the agent's transformer pipeline initializes the holder before any code path reads it
  4. 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

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


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