pinpoint-apm/pinpoint · error · IOException

not found class. classLoader=${cl}, classInternalName=${clas

Error message

not found class. classLoader=${cl}, classInternalName=${classInternalName}

What it means

IOException thrown by ClassReaderWrapper when getResourceAsStream(classInternalName + ".class") returns null, meaning the class bytecode could not be located in the given classloader. Pinpoint needs the raw .class bytes to build a ClassReader for instrumentation analysis.

Source

Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/classreading/ClassReaderWrapper.java:88

    }

    // classloader and class internal name.
    public ClassReaderWrapper(final ClassLoader classLoader, final String classInternalName, final boolean readAttributes) throws IOException {
        Objects.requireNonNull(classInternalName, "classInternalName");

        ClassLoader cl = classLoader;
        if (cl == null) {
            cl = ClassLoader.getSystemClassLoader();
            if (cl == null) {
                // system fail.
                throw new IOException("system classloader is null.");
            }
        }

        final String classPath = classInternalName.concat(".class");
        final InputStream in = cl.getResourceAsStream(classPath);
        if (in == null) {
            throw new IOException("not found class. classLoader=" + cl + ", classInternalName=" + classInternalName);
        }

        byte[] bytes = IOUtils.toByteArray(in);
        this.classReader = new ClassReader(bytes);
        if (readAttributes) {
            readAttributes();
        }
    }

    // class's access flags.
    public int getAccess() {
        return this.classReader.getAccess();
    }

    // class version.
    public int getVersion() {
        return this.classReader.readShort(6);
    }

View on GitHub (pinned to 744c3d3075)

Solutions

  1. Verify the classInternalName matches the actual class location (package/path, no leading slash issues).
  2. Pass the classloader that actually defines/loads the class (e.g. clazz.getClassLoader()), not an arbitrary one.
  3. If the class is runtime-generated, read bytes from the generator instead of relying on a classloader resource.
  4. Log the classloader's classpath/URLs and confirm the jar containing the class is present.

Example fix

// before
wrapper.readClassInternalName("com/foo/Generated$Proxy", parentLoader);
// after
wrapper.readClassInternalName("com/foo/Generated$Proxy", proxyClass.getClassLoader());
Defensive patterns

Strategy: validation

Validate before calling

String path = classInternalName.replace('.', '/') + ".class";
if (cl.getResource(path) == null) { /* class not visible from this loader - pick another */ }

Try / catch

try { wrapper.readClassInternalName(name, cl); } catch (IOException e) { if (e.getMessage().startsWith("not found class")) { logger.warn("class {} invisible from {}", name, cl); } throw e; }

Prevention

When it happens

Trigger: ClassReaderWrapper invoked for an internal name whose resource is not visible from the supplied ClassLoader - the class is missing, not yet loaded/defined in that loader, or located in a parent/sibling loader.

Common situations: Classes generated at runtime (proxies, lambdas, codegen) that have no corresponding .class resource, classes in an app-server webapp loader accessed with the wrong (parent) loader, or shaded/relocated classes whose internal name changed.

Related errors


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