Skip to content

Commit f2a889c

Browse files
committed
Hold reference to intercepted Logger to prevent GC wiping out the interception.
1 parent 09fbba2 commit f2a889c

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

logunit-jul/src/main/java/io/github/netmikey/logunit/jul/JulLogProvider.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ public class JulLogProvider extends BaseLogProvider {
2323

2424
private final ListHandler listHandler = new ListHandler();
2525

26+
// We hold references to loggers we have intercepted to avoid them being garbage collected and reconstructed without
27+
// our handler in between beforeTestExecution and the actual test business logic.
28+
private final Map<String, Logger> loggers = new HashMap<>();
29+
2630
private final Map<String, Level> originalLevels = new HashMap<>();
2731

2832
@Override
@@ -65,6 +69,7 @@ private void addAppenderToLogger(String name, Level level) {
6569

6670
private void addAppenderToLogger(Logger logger, Level level) {
6771
logger.addHandler(listHandler);
72+
loggers.put(logger.getName(), logger);
6873
originalLevels.put(logger.getName(), logger.getLevel());
6974
logger.setLevel(level);
7075
}
@@ -75,6 +80,7 @@ private void detachAppenderFromLogger(String name) {
7580

7681
private void detachAppenderFromLogger(Logger logger) {
7782
logger.removeHandler(listHandler);
83+
loggers.remove(logger.getName());
7884
Level originalLevel = originalLevels.get(logger.getName());
7985
if (originalLevel != null) {
8086
logger.setLevel(originalLevel);

logunit-jul/src/test/java/io/github/netmikey/logunit/jul/LogCapturerWithJulTest.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,13 @@
1919
public class LogCapturerWithJulTest {
2020

2121
@RegisterExtension
22-
LogCapturer testLoggerInfoCapturer = LogCapturer.create().captureForType(LogCapturerWithJulTest.class);
22+
LogCapturer testLoggerInfoCapturer = LogCapturer.create().captureForType(LoggingObject.class);
2323

2424
@RegisterExtension
2525
LogCapturer namedLoggerWarnCapturer = LogCapturer.create().captureForLogger(LOGGER_NAME, Level.WARN);
2626

2727
private static final String LOGGER_NAME = "CUSTOM_LOGGER";
2828

29-
private Logger testLogger = Logger.getLogger(LogCapturerWithJulTest.class.getName());
30-
3129
private Logger namedLogger = Logger.getLogger(LOGGER_NAME);
3230

3331
/**
@@ -38,11 +36,15 @@ public class LogCapturerWithJulTest {
3836
* <li>that the namedLogger (by logger name) captures only the WARN level
3937
* and above as specified</li>
4038
* <li>both loggers and their capturers don't affeact each other</li>
39+
* <li>logger is not garbage collected, losing interception</li>
4140
* </ul>
4241
*/
4342
@Test
44-
public void test1CaptureMessages() {
45-
logEverythingOnce(testLogger);
43+
public void test1CaptureMessages() throws InterruptedException {
44+
System.gc();
45+
Thread.sleep(50);
46+
47+
logEverythingOnce(new LoggingObject().testLogger);
4648
logEverythingOnce(namedLogger);
4749

4850
Assertions.assertEquals(3, testLoggerInfoCapturer.size(),
@@ -83,4 +85,10 @@ private void logEverythingOnce(Logger logger) {
8385
logger.warning("Some warning message");
8486
logger.severe("Some severe message");
8587
}
88+
89+
// The logger will not be until the object is. This tests that log messages will be captured without allowing
90+
// the intercepted Logger to be garbage collected.
91+
private static class LoggingObject {
92+
Logger testLogger = Logger.getLogger(LoggingObject.class.getName());
93+
}
8694
}

0 commit comments

Comments
 (0)