Skip to content

Restore the java.util.logging root handlers after an embedded execution - #68

Merged
slachiewicz merged 1 commit into
mainfrom
agent/embedded-restore-jul-handlers
Oct 6, 2026
Merged

slachiewicz merged 1 commit into
mainfrom
agent/embedded-restore-jul-handlers

Conversation

@slachiewicz

Copy link
Copy Markdown
Member

CI on Windows has been failing with an executionError in ToolboxExecutorToolTest (#64, #65, Dependabot PRs such as #62):

java.lang.NoClassDefFoundError: org/slf4j/spi/LocationAwareLogger
	at org.slf4j.bridge.SLF4JBridgeHandler.publish(SLF4JBridgeHandler.java:312)
	at java.logging/java.util.logging.Logger.log(Logger.java:962)
Caused by: java.lang.ClassNotFoundException: org.slf4j.spi.LocationAwareLogger
	at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:42)

Maven 4's LookupInvoker.activateLogging() removes the handlers of the java.util.logging root logger and installs jul-to-slf4j's SLF4JBridgeHandler (Maven 3.9 doesn't ship jul-to-slf4j). Run embedded, that root logger belongs to the caller's JVM, and the handler's classes come from Maven's class realm. EmbeddedMavenExecutor restores stdin/stdout/stderr, the context class loader and the system properties after a run, but not the logging handlers. Once the realm is closed, the next java.util.logging record in the JVM fails. Surefire reports that as executionError because it isn't tied to a test method. It only showed up on Windows because something in the test JVM logs through java.util.logging there after an embedded Maven 4 run; the leak itself happens on every OS.

execute() now captures the root logger's handlers before the run and puts them back in its finally block, next to the other restores. It captures per execution, not in the constructor, so a change the caller makes between executions is kept (see E5 in #49). module-info gains requires java.logging.

EmbeddedJulHandlersTest runs -v embedded on Maven 3 and Maven 4 and checks the root handlers after the execution and after close(), then logs through java.util.logging. Without the fix, the Maven 4 case fails on Linux too: the root handlers are [SLF4JBridgeHandler] instead of [ConsoleHandler], and with that check skipped, the log call throws the NoClassDefFoundError above. With the fix, mvn verify for the module passes.

Maven itself could also uninstall the handler when the invoker closes; until then, the executor protects its callers.

🤖 Generated with Claude Code

Maven 4 replaces the handlers of the java.util.logging root logger with
jul-to-slf4j's SLF4JBridgeHandler. Embedded, that is the caller's JVM,
and the handler's classes come from Maven's realm: after close(), every
java.util.logging record of the caller fails with NoClassDefFoundError:
org/slf4j/spi/LocationAwareLogger, which surefire reports as
executionError (seen on Windows CI). Put back the root handlers the JVM
had before each execution.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@slachiewicz
slachiewicz merged commit 0d2234d into main Oct 6, 2026
23 checks passed
@slachiewicz
slachiewicz deleted the agent/embedded-restore-jul-handlers branch October 6, 2026 18:36
@github-actions github-actions Bot added this to the 1.0.1 milestone Oct 6, 2026
@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown

@slachiewicz Please assign appropriate label to PR according to the type of change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant