Repository navigation
[SUREFIRE-3460] Don't NPE when StackWalkerStrategy inits with a null TCCL - #3464
Merged
olamy merged 2 commits intoSep 10, 2026
Merged
Conversation
MatthewRyanRead
approved these changes
Sep 9, 2026
MatthewRyanRead
left a comment
There was a problem hiding this comment.
Nice, hopefully they will accept this for 3.6.1.
elharo
requested changes
Sep 9, 2026
| static { | ||
| ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); | ||
| // java.lang.StackWalker is a JDK class; do not depend on the current thread's TCCL, which can be null | ||
| // (Attach Listener, user threads that cleared it). A null TCCL used to NPE in tryLoadClass and poison |
Contributor
There was a problem hiding this comment.
only describe current code, not what used to happen
| try { | ||
| return classLoader.loadClass(className); | ||
| } catch (NoClassDefFoundError | ClassNotFoundException ignore) { | ||
| } catch (NoClassDefFoundError | ClassNotFoundException | RuntimeException ignore) { |
Contributor
There was a problem hiding this comment.
return null should probably move into this catch block
Don't catch RuntimeException. Only catch more specific exceptions you actually expect. Otherwise we'll hide bugs we should know about
β¦TCCL tryLoadClass treated a null ClassLoader as loadClass on null and threw, which poisoned StackWalkerStrategy.<clinit> for the rest of the forked JVM. Load JDK types from the defining class loader instead, and treat a null loader as not found. Fixes apache#3460 Signed-off-by: Burak KALAYCI <kalayciburak1996@gmail.com>
kalayciburak
force-pushed
the
fix-3460-null-tccl-stackwalker
branch
from
September 9, 2026 12:11
d3cd380 to
0349086
Compare
olamy
requested changes
Sep 10, 2026
|
|
||
| @Test | ||
| void getStackDoesNotThrowWhenContextClassLoaderIsNull() { | ||
| ClassLoader original = Thread.currentThread().getContextClassLoader(); |
Member
There was a problem hiding this comment.
Thanks for your pull request.
Could you please provide an IT test as well. A real as simple as possible project reproducing the issue
Contributor
Author
There was a problem hiding this comment.
added a tiny IT, same repro as on the issue (null TCCL thread + one println). pushed
Minimal project that prints from a thread whose context class loader is null, the same repro as on the issue.
Closed
1 task
1 task
marevol
added a commit
to codelibs/fess-parent
that referenced
this pull request
Oct 1, 2026
maven-surefire-plugin and maven-failsafe-plugin 3.6.0 (bumped in #84) add StackWalkerStrategy, whose static initializer calls Thread.currentThread().getContextClassLoader().loadClass(...). The JVM's "Attach Listener" thread has no context class loader, so the initializer throws an NPE whenever that thread prints to the captured stdout/stderr. Mockito's self-attach prints the dynamic agent loading warning from that thread, so the agent fails to start ("Could not initialize plugin: interface org.mockito.plugins.MockMaker"), and every later console line in the same JVM fails with NoClassDefFoundError for StackWalkerStrategy. The fess-crawler CI build went from passing to failing on the same commit once the snapshot picked up 3.6.0. Running the same tests with the plugin version forced shows 13 errors with 3.6.0 and none with 3.5.6, and the whole fess-crawler module passes with 3.5.6. The upstream fix is SUREFIRE-3460 (apache/maven-surefire#3464), scheduled for 3.6.1, which is not released yet.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
StackWalkerStrategy.<clinit>loadedjava.lang.StackWalkerthrough the current thread's TCCL. When that loader isnull(user threads that cleared it, or the JVMAttach Listenerwhile a dynamic agent is installed),ReflectionUtils.tryLoadClassthrew an uncaughtNullPointerException. That failed class initialization and every later reference becameNoClassDefFoundError: Could not initialize class ...StackWalkerStrategy.Because console capture walks the stack on every
println, a write from a null-TCCL thread could poison the forked JVM. On 3.6.0 this also surfaces as a confusing Byte Buddy / BlockHound self-attach failure when the JDK prints the dynamic-agent warning fromAttach Listener.This change:
ClassLoaderas "not found" intryLoadClass(ClassNotFoundException/NoClassDefFoundErroronly)StackWalker/StackFramefromStackWalkerStrategy's defining loader (system loader if that is bootstrapnull), since those types are JDK classes and do not need the TCCLFixes #3460
Following this checklist to help us incorporate your contribution quickly and easily:
mvn clean installto make sure basic checks pass. A more thorough check will be performed on your pull request automatically.mvn -Prun-its clean install).Validation (JDK 21, Maven 3.9.11):
mvn -pl surefire-api -Dtest=ReflectionUtilsTest,StackTraceProviderTest testβ 23 tests, 0 failuresmvn -pl surefire-api testβ 217 tests, 0 failures, 6 skippedIf your pull request is about ~20 lines of code you don't need to sign an
Individual Contributor License Agreement if you are unsure
please ask on the developers list.
To make clear that you license your contribution under
the Apache License Version 2.0, January 2004
you have to acknowledge this by using the following check-box.
I hereby declare this contribution to be licenced under the Apache License Version 2.0, January 2004
In any other case, please file an Apache Individual Contributor License Agreement.