diff --git a/core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java b/core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java index e093a4ce6a3..8ca48215727 100644 --- a/core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java +++ b/core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java @@ -76,6 +76,7 @@ import org.springframework.util.StringUtils; * @author Ben Hale * @author Ralph Goers * @author Piotr P. Karwasz + * @author Dhruv Rastogi * @since 1.2.0 */ public class Log4J2LoggingSystem extends AbstractLoggingSystem { @@ -118,6 +119,8 @@ public class Log4J2LoggingSystem extends AbstractLoggingSystem { private final LoggerContext loggerContext; + private boolean bridgeHandlerInstalled; + /** * Create a new {@link Log4J2LoggingSystem} instance. * @param classLoader the class loader to use. @@ -189,6 +192,7 @@ public class Log4J2LoggingSystem extends AbstractLoggingSystem { && isLog4jBridgeHandlerAvailable()) { removeDefaultRootHandler(); Log4jBridgeHandler.install(false, null, true); + this.bridgeHandlerInstalled = true; return true; } } @@ -454,8 +458,9 @@ public class Log4J2LoggingSystem extends AbstractLoggingSystem { @Override public void cleanUp() { - if (isLog4jBridgeHandlerAvailable()) { + if (this.bridgeHandlerInstalled) { removeLog4jBridgeHandler(); + this.bridgeHandlerInstalled = false; } super.cleanUp(); LoggerContext loggerContext = getLoggerContext(); diff --git a/core/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java b/core/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java index 3c991980ad5..b772c0885e3 100644 --- a/core/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java +++ b/core/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java @@ -75,6 +75,7 @@ import org.springframework.util.StringUtils; * @author Dave Syer * @author Andy Wilkinson * @author Ben Hale + * @author Dhruv Rastogi * @since 1.0.0 */ public class LogbackLoggingSystem extends AbstractLoggingSystem implements BeanFactoryInitializationAotProcessor { @@ -111,6 +112,8 @@ public class LogbackLoggingSystem extends AbstractLoggingSystem implements BeanF private final StatusPrinter2 statusPrinter = new StatusPrinter2(); + private boolean bridgeHandlerInstalled; + public LogbackLoggingSystem(ClassLoader classLoader) { super(classLoader); } @@ -141,6 +144,7 @@ public class LogbackLoggingSystem extends AbstractLoggingSystem implements BeanF if (isBridgeJulIntoSlf4j()) { removeJdkLoggingBridgeHandler(); SLF4JBridgeHandler.install(); + this.bridgeHandlerInstalled = true; } } catch (Throwable ex) { @@ -334,8 +338,9 @@ public class LogbackLoggingSystem extends AbstractLoggingSystem implements BeanF LoggerContext context = getLoggerContext(); markAsUninitialized(context); super.cleanUp(); - if (isBridgeHandlerAvailable()) { + if (this.bridgeHandlerInstalled) { removeJdkLoggingBridgeHandler(); + this.bridgeHandlerInstalled = false; } context.getStatusManager().clear(); context.getTurboFilterList().remove(SUPPRESS_ALL_FILTER); diff --git a/core/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java b/core/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java index ecb14ddbd98..da92666cc7c 100644 --- a/core/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java +++ b/core/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java @@ -88,6 +88,7 @@ import static org.mockito.Mockito.times; * @author Ben Hale * @author Madhura Bhave * @author Piotr P. Karwasz + * @author Dhruv Rastogi */ @ExtendWith(OutputCaptureExtension.class) @ClassPathExclusions("logback-*.jar") @@ -406,6 +407,25 @@ class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests { assertThat(logger.getLevel()).isEqualTo(Level.FINE); } + @Test + void cleanUpLeavesBridgeHandlerInstalledByTheApplicationInPlace() { + java.util.logging.Logger rootLogger = java.util.logging.Logger.getLogger(""); + Log4jBridgeHandler.install(false, null, true); + try { + assertThat(rootLogger.getHandlers()).hasAtLeastOneElementOfType(Log4jBridgeHandler.class); + this.loggingSystem.beforeInitialize(); + this.loggingSystem.cleanUp(); + assertThat(rootLogger.getHandlers()).hasAtLeastOneElementOfType(Log4jBridgeHandler.class); + } + finally { + for (Handler handler : rootLogger.getHandlers()) { + if (handler instanceof Log4jBridgeHandler) { + rootLogger.removeHandler(handler); + } + } + } + } + @Test void shutdownHookIsDisabled() { assertThat( diff --git a/core/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java b/core/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java index 6adaeb4d8de..02d9a1d39b4 100644 --- a/core/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java +++ b/core/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java @@ -107,6 +107,7 @@ import static org.mockito.Mockito.times; * @author Scott Frederick * @author Jonatan Ivanov * @author Moritz Halbritter + * @author Dhruv Rastogi */ @ExtendWith(OutputCaptureExtension.class) @ClassPathExclusions({ "log4j-core-*.jar", "log4j-api-*.jar" }) @@ -340,6 +341,20 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests { assertThat(bridgeHandlerInstalled()).isFalse(); } + @Test + void cleanUpLeavesBridgeHandlerInstalledByTheApplicationInPlace() { + SLF4JBridgeHandler.install(); + try { + assertThat(bridgeHandlerInstalled()).isTrue(); + this.loggingSystem.beforeInitialize(); + this.loggingSystem.cleanUp(); + assertThat(bridgeHandlerInstalled()).isTrue(); + } + finally { + SLF4JBridgeHandler.uninstall(); + } + } + @Test void standardConfigLocations() { String[] locations = this.loggingSystem.getStandardConfigLocations();