pinpoint-apm/pinpoint · warning

duplicated pluginClass

Error message

duplicated pluginClass {}

What it means

In PlainClassLoaderHandler's class cache, putClass uses putIfAbsent and logs this warn when a class with the same name is already cached, meaning two Class objects for one plugin class name were produced concurrently. The previously cached class wins; nothing is thrown. It usually indicates a race between concurrent define0 calls for the same class.

Solutions

  1. Verify the surviving cached class is the one actually used by all call sites (getClass returns the first).
  2. Avoid racing plugin initialization — synchronize plugin setup at startup.
  3. Check for duplicate plugin jars or duplicate transform requests for the same class.
  4. If benign (same bytecode), this warn can be tolerated; otherwise investigate the concurrent define0 path.

Example fix

// before
final Class<?> dup = cache.putIfAbsent(className, clazz);
if (dup != null) { logger.warn("duplicated pluginClass {}", className); }
// after
// ensure single-threaded plugin class definition:
synchronized (defineLock) { cache.putIfAbsent(className, defineClass(className)); }
Defensive patterns

Strategy: validation

Validate before calling

Class<?> existing = cache.get(className);
if (existing != null) { return existing; } // skip redefinition

Try / catch

synchronized (pluginDefineLock) { cache.putIfAbsent(className, defineClass(className)); }

Prevention

When it happens

Trigger: Two threads concurrently defining/loading the same plugin class in the same classloader so putIfAbsent finds an existing entry; repeated plugin initialization racing during agent startup or class transformation.

Common situations: High-concurrency first-use of an instrumented class; plugin loaded by multiple matchers simultaneously; hot redeploy racing with in-flight requests.

Related errors


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

Appendix: source

Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/classloading/PlainClassLoaderHandler.java:347

        public PluginLock getPluginLock(String jarFile) {
            final PluginLock exist = this.pluginLock.get(jarFile);
            if (exist != null) {
                return exist;
            }

            final PluginLock newPluginLock = new PluginLock();
            final PluginLock old = this.pluginLock.putIfAbsent(jarFile, newPluginLock);
            if (old != null) {
                return old;
            }
            return newPluginLock;
        }

        public void putClass(String className, Class<?> clazz) {
            final Class<?> duplicatedClass = this.classCache.putIfAbsent(className, clazz);
            if (duplicatedClass != null) {
                if (logger.isWarnEnabled()) {
                    logger.warn("duplicated pluginClass {}", className);
                }
            }
        }

        public Class<?> getClass(String className) {
            return this.classCache.get(className);
        }

        public boolean containsClass(String className) {
            return this.classCache.containsKey(className);
        }
    }

    private static class PluginLock {

        private boolean loaded = false;

        public boolean isLoaded() {

View on GitHub (pinned to 744c3d3075)