pinpoint-apm/pinpoint · warning

LoggerBinder is already initialized

Error message

LoggerBinder is already initialized

What it means

Log4j2LoggerBinderInitializer.beforeClass() attempts PluginLogManager.initialize(loggerBinder); if it returns false, a binder (with its own classloader) is already registered, and this warning is logged. PluginLogManager only allows one logger binder per classloader scope, so double initialization indicates the test/class ran twice in the same JVM or the binder was never unregistered.

Source

Thrown at agent-module/profiler-logging/src/main/java/com/navercorp/pinpoint/profiler/logging/Log4j2LoggerBinderInitializer.java:36

import com.navercorp.pinpoint.bootstrap.logging.PluginLogManager;
import com.navercorp.pinpoint.bootstrap.logging.PluginLogger;
import com.navercorp.pinpoint.bootstrap.logging.PluginLoggerBinder;
import org.apache.logging.log4j.LogManager;

/**
 * For unit test to register/unregister loggerBinder.
 *
 * @author emeroad
 */
public class Log4j2LoggerBinderInitializer {

    private static final PluginLoggerBinder loggerBinder = new Log4j2Binder(LogManager.getContext());

    public static void beforeClass() {
        if (!PluginLogManager.initialize(loggerBinder)) {
            PluginLogger logger = loggerBinder.getLogger(Log4j2LoggerBinderInitializer.class.getName());
            logger.warn("LoggerBinder is already initialized");
        }
    }

    public static void afterClass() {
        PluginLogManager.unregister(loggerBinder);
    }
}

View on GitHub (pinned to 744c3d3075)

Solutions

  1. Ensure afterClass()/PluginLogManager.unregister(binder) is always called (e.g. @AfterClass)
  2. Check that only one code path initializes the logger binder per classloader
  3. Run tests without JVM reuse (forkPerTest) if binder state leaks
  4. Inspect PluginLogManager to see which classloader bound the earlier binder

Example fix

// before
@BeforeClass
public static void before() { Log4j2LoggerBinderInitializer.beforeClass(); }
// after
@BeforeClass
public static void before() { Log4j2LoggerBinderInitializer.beforeClass(); }
@AfterClass
public static void after() { Log4j2LoggerBinderInitializer.afterClass(); }
Defensive patterns

Strategy: try-catch

Validate before calling

if (com.navercorp.pinpoint.profiler.logging.PluginLogManager.class.getClassLoader() == binder.getClass().getClassLoader()) { /* same CL — risk of double init */ }

Try / catch

if (!PluginLogManager.initialize(binder)) { logger.warn("binder already bound by another initializer; reusing existing binder"); }

Prevention

When it happens

Trigger: beforeClass() called when PluginLogManager already holds an initialized binder — e.g. two test classes share a JVM and the previous binder was not unregistered via afterClass().

Common situations: JUnit tests using a shared JVM without afterClass() cleanup; agent started twice in the same JVM; profiler-logging initialized both by bootstrap and by test harness.

Related errors


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