{"record":{"id":"a24648e49b62ba1d","repo":"pinpoint-apm/pinpoint","slug":"loggerbinder-is-already-initialized","errorCode":null,"errorMessage":"LoggerBinder is already initialized","messagePattern":"LoggerBinder is already initialized","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"agent-module/profiler-logging/src/main/java/com/navercorp/pinpoint/profiler/logging/Log4j2LoggerBinderInitializer.java","lineNumber":36,"sourceCode":"\nimport com.navercorp.pinpoint.bootstrap.logging.PluginLogManager;\nimport com.navercorp.pinpoint.bootstrap.logging.PluginLogger;\nimport com.navercorp.pinpoint.bootstrap.logging.PluginLoggerBinder;\nimport org.apache.logging.log4j.LogManager;\n\n/**\n * For unit test to register/unregister loggerBinder.\n *\n * @author emeroad\n */\npublic class Log4j2LoggerBinderInitializer {\n\n    private static final PluginLoggerBinder loggerBinder = new Log4j2Binder(LogManager.getContext());\n\n    public static void beforeClass() {\n        if (!PluginLogManager.initialize(loggerBinder)) {\n            PluginLogger logger = loggerBinder.getLogger(Log4j2LoggerBinderInitializer.class.getName());\n            logger.warn(\"LoggerBinder is already initialized\");\n        }\n    }\n\n    public static void afterClass() {\n        PluginLogManager.unregister(loggerBinder);\n    }\n}\n","sourceCodeStart":18,"sourceCodeEnd":44,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/agent-module/profiler-logging/src/main/java/com/navercorp/pinpoint/profiler/logging/Log4j2LoggerBinderInitializer.java#L18-L44","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","solutions":["Ensure afterClass()/PluginLogManager.unregister(binder) is always called (e.g. @AfterClass)","Check that only one code path initializes the logger binder per classloader","Run tests without JVM reuse (forkPerTest) if binder state leaks","Inspect PluginLogManager to see which classloader bound the earlier binder"],"exampleFix":"// before\n@BeforeClass\npublic static void before() { Log4j2LoggerBinderInitializer.beforeClass(); }\n// after\n@BeforeClass\npublic static void before() { Log4j2LoggerBinderInitializer.beforeClass(); }\n@AfterClass\npublic static void after() { Log4j2LoggerBinderInitializer.afterClass(); }","handlingStrategy":"try-catch","validationCode":"if (com.navercorp.pinpoint.profiler.logging.PluginLogManager.class.getClassLoader() == binder.getClass().getClassLoader()) { /* same CL — risk of double init */ }","typeGuard":null,"tryCatchPattern":"if (!PluginLogManager.initialize(binder)) { logger.warn(\"binder already bound by another initializer; reusing existing binder\"); }","preventionTips":["Always pair beforeClass() with afterClass() in @BeforeClass/@AfterClass","Initialize the logger binder from exactly one code path per classloader","Avoid JVM reuse across tests that bind loggers statically","Check PluginLogManager state before re-initializing"],"tags":["logging","log4j2","initialization","classloader","testing"],"backgroundTag":"double-initialization","analyzedSha":"744c3d3075e595656abb1ae331ad2c0e4c9eb996","analyzedAt":"2026-09-07T18:48:45.289Z","contentChangedAt":"2026-09-07T18:48:45.289Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}