pinpoint-apm/pinpoint · error · PinpointException
Failed to load plugin class ${className} with classLoader ${
Error message
Failed to load plugin class ${className} with classLoader ${classLoader} What it means
PluginClassInjector.injectClass() is the single entry point that loads plugin classes into application classloaders, dispatching to bootstrap/URLClassLoader/plain handlers. Any Throwable escaping those handlers (IOException reading the jar, 'interface not found' PinpointException, LinkageError, etc.) is caught and rethrown as a PinpointException wrapping the original cause. The message only names the class and classloader — the actionable information is in the cause chain.
Source
Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/classloading/PluginClassInjector.java:80
@Override
public <T> Class<? extends T> injectClass(ClassLoader classLoader, String className) {
try {
if (bootstrapCore.isBootstrapPackage(className)) {
return bootstrapCore.loadClass(className);
}
if (bootstrapClassLoader == classLoader) {
return bootstrapClassLoaderHandler.injectClass(null, className);
} else if (classLoader instanceof URLClassLoader) {
return urlClassLoaderHandler.injectClass(classLoader, className);
} else {
return plainClassLoaderHandler.injectClass(classLoader, className);
}
} catch (Throwable e) {
// fixed for LinkageError
logger.warn("Failed to load plugin class {} with classLoader {}", className, classLoader, e);
throw new PinpointException("Failed to load plugin class " + className + " with classLoader " + classLoader, e);
}
}
@Override
public InputStream getResourceAsStream(ClassLoader targetClassLoader, String internalName) {
try {
if (bootstrapCore.isBootstrapPackageByInternalName(internalName)) {
return bootstrapCore.openStream(internalName);
}
if (targetClassLoader == null) {
return bootstrapClassLoaderHandler.getResourceAsStream(null, internalName);
} else if (targetClassLoader instanceof URLClassLoader) {
final URLClassLoader urlClassLoader = (URLClassLoader) targetClassLoader;
return urlClassLoaderHandler.getResourceAsStream(urlClassLoader, internalName);
} else {
return plainClassLoaderHandler.getResourceAsStream(targetClassLoader, internalName);
}
} catch (Throwable e) {View on GitHub (pinned to 744c3d3075)
Solutions
- Read the full logged stack trace ('Failed to load plugin class ...') and fix the root cause it names (jar read fail, interface not found, reflective access, etc.).
- Verify the plugin jar is complete and readable: `unzip -t`, correct permissions, and matching plugin/agent versions.
- Confirm the target JVM supports the plugin classes' class-file version (plugin built with a newer JDK than the app's JVM — rebuild plugin with --release matching the runtime).
- Check the plugin dir for duplicate or overlapping plugin jars; remove older versions.
- If reflective access is the cause, upgrade the pinpoint agent to a version compatible with your JDK or add the required --add-opens/--add-exports JVM flags.
- Test the plugin outside pinpoint (plain loadClass) to confirm the jar is self-consistent.
Example fix
// caller side: always inspect the cause, the message is only a wrapper
try {
injector.injectClass(appClassLoader, "com.example.PluginTransformer");
} catch (PinpointException e) {
logger.error("plugin injection failed; root cause:", e.getCause());
// fix root cause (jar integrity / JDK flags / version alignment) before retrying
} Defensive patterns
Strategy: try-catch
Try / catch
try {
Class<?> c = injector.injectClass(targetClassLoader, pluginClassName);
} catch (PinpointException e) {
// this message is only a wrapper; the actionable info is the cause
Throwable root = e;
while (root.getCause() != null) root = root.getCause();
logger.error("plugin injection of {} failed, root cause {}: {}",
pluginClassName, root.getClass().getName(), root.getMessage());
// dispatch on root cause: IOException -> jar integrity; 'not found' -> packaging; LinkageError -> duplicates/JDK
} Prevention
- Always log the full stack trace (with causes), not just e.getMessage().
- Keep plugin jars complete, checksum-verified, and version-matched to the agent.
- Test the target JDK against the agent version matrix before upgrading the app JVM.
- Check the plugin directory for duplicate/overlapping jars at deploy time.
- Run the agent in staging with debug logging enabled for plugin loading before production rollouts.
When it happens
Trigger: Any failure inside urlClassLoaderHandler.injectClass() (addURL reflection failure, 'invalid ClassLoader') or plainClassLoaderHandler.injectClass() (jar read IOException from readJar(), missing-interface PinpointException, ClassNotFoundException wrapped as RuntimeException, LinkageError/duplicate class definition) while injecting a plugin class into the target application classloader.
Common situations: Corrupted or unreadable plugin jars; incomplete plugin jars missing dependency interfaces; running the agent on a JDK where reflective defineClass/addURL is blocked (module system restrictions); plugin classes compiled for a higher class-file version than the target JVM; two plugins defining the same class into one classloader.
Related errors
- ${interfaceName} not found
- ${pluginConfig.getPluginJarURLExternalForm()} read fail.${ex
- J9BootLoader create fail Caused by:
- initialize fail Caused by:
- invoke fail Caused by:
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/1ee6a4213800d269.
Report an issue: GitHub.