This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch fix/identity-hashmap-request-cache
in repository https://gitbox.apache.org/repos/asf/maven.git

commit 0873e99ebc7cecf072bf2384a0ff6c499c4288a4
Author: Guillaume Nodet <[email protected]>
AuthorDate: Wed May 27 09:41:23 2026 +0200

    Fix deadlock in AbstractRequestCache.requests() due to unstable hashCode
    
    The `requests()` method uses a HashMap to coordinate batch results between
    the batch supplier and the individual CachingSupplier instances. When a
    request object's hashCode() changes between HashMap.put() and
    HashMap.containsKey() (e.g., because ResolverRequest includes a
    RequestTrace with mutable ModelBuilderRequest data), the key is stored
    in one bucket but looked up in another, causing containsKey() to return
    false. The individualSupplier then waits forever for a result that is
    already in the map but unreachable.
    
    Switch to IdentityHashMap which uses System.identityHashCode() and
    reference equality (==), both of which are stable regardless of
    mutable object state. This is safe because the code always uses the
    same object reference for put and get.
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
 .../main/java/org/apache/maven/impl/cache/AbstractRequestCache.java   | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/AbstractRequestCache.java
 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/AbstractRequestCache.java
index 0b7fac393b..0dc5a7d0f0 100644
--- 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/AbstractRequestCache.java
+++ 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/AbstractRequestCache.java
@@ -19,7 +19,7 @@
 package org.apache.maven.impl.cache;
 
 import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
@@ -85,7 +85,7 @@ public <REQ extends Request<?>, REP extends Result<REQ>> REP 
request(REQ req, Fu
     @SuppressWarnings("unchecked")
     public <REQ extends Request<?>, REP extends Result<REQ>> List<REP> 
requests(
             List<REQ> reqs, Function<List<REQ>, List<REP>> supplier) {
-        final Map<REQ, Object> nonCachedResults = new HashMap<>();
+        final Map<REQ, Object> nonCachedResults = new IdentityHashMap<>();
         List<RequestResult<REQ, REP>> allResults = new 
ArrayList<>(reqs.size());
 
         Function<REQ, REP> individualSupplier = req -> {

Reply via email to