Description
Maven 4 hangs indefinitely during builds when the local repository is empty (e.g. -Dmaven.repo.local=/fresh/path). The build freezes at maven-remote-resources-plugin:process while resolving parent POMs of transitive dependencies.
The same build completes in seconds with a populated local repository.
Steps to Reproduce
git clone --depth 1 https://github.com/apache/httpcomponents-stylecheck.git
cd httpcomponents-stylecheck
# Works fine (cached):
mvn -B clean package -DskipTests
# Hangs forever (empty repo):
mvn -B clean package -DskipTests -Dmaven.repo.local=/tmp/fresh-repo
The build hangs at:
[INFO] --- remote-resources:3.0.0:process (process-resource-bundles) @ hc-stylecheck ---
[INFO] Preparing remote bundle org.apache:apache-jar-resource-bundle:1.4
[INFO] Copying 3 resources from 1 bundle.
Thread Dump Analysis
The main thread is stuck in AbstractRequestCache.lambda$requests$0 (line 95) calling Object.wait() on a HashMap that it already holds the lock on:
"main" in Object.wait()
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait0(Native Method)
- waiting on <0x000000070dadf9a8> (a java.util.HashMap)
at org.apache.maven.impl.cache.AbstractRequestCache.lambda$requests$0(AbstractRequestCache.java:95)
- locked <0x000000070dadf9a8> (a java.util.HashMap)
at org.apache.maven.impl.cache.CachingSupplier.apply(CachingSupplier.java:50)
at org.apache.maven.impl.cache.AbstractRequestCache.requests(AbstractRequestCache.java:144)
at org.apache.maven.impl.AbstractSession.requests(AbstractSession.java:177)
at org.apache.maven.impl.DefaultArtifactResolver.doResolve(DefaultArtifactResolver.java:106)
at org.apache.maven.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:65)
at org.apache.maven.impl.AbstractSession.resolveArtifact(AbstractSession.java:689)
at org.apache.maven.impl.resolver.DefaultModelResolver.getPath(DefaultModelResolver.java:181)
at org.apache.maven.impl.resolver.DefaultModelResolver.doResolveModel(DefaultModelResolver.java:155)
at org.apache.maven.impl.resolver.DefaultModelResolver.resolveModel(DefaultModelResolver.java:116)
at org.apache.maven.impl.model.DefaultModelBuilder...resolveParent(DefaultModelBuilder.java:1101)
...
at org.apache.maven.plugin.resources.remote.ProcessRemoteResourcesMojo.getProjects(ProcessRemoteResourcesMojo.java:665)
Meanwhile, all 15 worker threads (5× BfDependencyCollector, 5× BasicRepositoryConnector, 5× resolver) are idle in LinkedBlockingQueue.take(), waiting for work that is never submitted.
Root Cause
This appears to be a missed-signal deadlock in AbstractRequestCache / CachingSupplier:
- The main thread enters
CachingSupplier.apply() to resolve an artifact
- Inside, it calls
Object.wait() on a HashMap, expecting another thread to resolve the artifact and call notify()
- But the resolution work is never dispatched to the worker threads — they sit idle in their thread pool queues
- The main thread waits forever
When the local repo is populated, the CachingSupplier returns the cached result immediately without entering the wait path. The deadlock only triggers when actual remote resolution is needed.
Impact
This affects any project using maven-remote-resources-plugin (very common — it's bound by default in the Apache parent POM) when built with a fresh local repository. This is the standard CI scenario where each build starts with an empty local repo.
In the maven4-testing suite (testing ~966 Apache projects against Maven 4), this deadlock caused 21 of 57 failures — all were 1-hour timeouts on projects that build fine on Maven 3 in under 6 minutes.
Environment
- Maven: 4.1.0-SNAPSHOT (commit 595458c)
- Java: OpenJDK 25.0.3+9-LTS
- OS: Linux
- Plugin: maven-remote-resources-plugin 3.0.0
Full thread dump attached: all 27 threads, showing the main thread's full stack trace and all idle worker threads.
Description
Maven 4 hangs indefinitely during builds when the local repository is empty (e.g.
-Dmaven.repo.local=/fresh/path). The build freezes atmaven-remote-resources-plugin:processwhile resolving parent POMs of transitive dependencies.The same build completes in seconds with a populated local repository.
Steps to Reproduce
The build hangs at:
Thread Dump Analysis
The main thread is stuck in
AbstractRequestCache.lambda$requests$0(line 95) callingObject.wait()on aHashMapthat it already holds the lock on:Meanwhile, all 15 worker threads (5×
BfDependencyCollector, 5×BasicRepositoryConnector, 5×resolver) are idle inLinkedBlockingQueue.take(), waiting for work that is never submitted.Root Cause
This appears to be a missed-signal deadlock in
AbstractRequestCache/CachingSupplier:CachingSupplier.apply()to resolve an artifactObject.wait()on aHashMap, expecting another thread to resolve the artifact and callnotify()When the local repo is populated, the
CachingSupplierreturns the cached result immediately without entering the wait path. The deadlock only triggers when actual remote resolution is needed.Impact
This affects any project using
maven-remote-resources-plugin(very common — it's bound by default in the Apache parent POM) when built with a fresh local repository. This is the standard CI scenario where each build starts with an empty local repo.In the maven4-testing suite (testing ~966 Apache projects against Maven 4), this deadlock caused 21 of 57 failures — all were 1-hour timeouts on projects that build fine on Maven 3 in under 6 minutes.
Environment
Full thread dump attached: all 27 threads, showing the main thread's full stack trace and all idle worker threads.