gnodet opened a new pull request, #2153:
URL: https://github.com/apache/maven-resolver/pull/2153

   ## Problem
   
   `PathConflictResolver` runs out of memory (`OutOfMemoryError: Java heap 
space`) on highly connected dependency graphs, such as a 813-module reactor 
where each module depends on ~9 others.
   
   Reproduced with `-Xmx512m`:
   ```
   java.lang.OutOfMemoryError: Java heap space
       at PathConflictResolver$Path.addChildren(PathConflictResolver.java:699)
       at 
PathConflictResolver$State.gatherCRNodes(PathConflictResolver.java:363)
   ```
   
   Workaround: `-Daether.conflictResolver.impl=classic`
   
   ## Root Cause
   
   `gatherCRNodes` performs a BFS/DFS traversal that creates a new `Path` 
object for **every edge** in the expanded dependency tree — not just one per 
`DependencyNode`. When the same node is reachable via N different parent paths, 
its entire subtree is traversed N times, leading to exponential `Path` 
allocation.
   
   For 813 modules × ~9 avg deps, this produces millions of `Path` objects 
instead of the ~7,500 that actually represent unique graph edges.
   
   ## Fix
   
   Two complementary changes:
   
   **1. Expansion deduplication** (the OOM fix):  
   Track which `DependencyNode` instances have already been expanded in an 
`IdentityHashMap<DependencyNode, Integer>` (mapped to expansion depth). When 
the same `DependencyNode` is encountered again via a different parent path, a 
`Path` entry is still created for it (so all occurrences appear in the conflict 
partition for winner selection), but its subtree is **not re-traversed**. If 
the same node is later reached at a shallower depth, it is re-expanded and the 
recorded minimum is updated.
   
   **2. Remove per-Path `HashSet` copy** (CPU/memory fix):  
   The `HashSet<String> conflictIdsOnPath` that was copied on every `Path` 
construction is dropped. Since expansion deduplication already bounds total 
path count to O(graph edges), the O(depth) parent-chain walk for 
`hasConflictIdOnPathToRoot` is sufficient and cheaper. This also eliminates the 
per-node allocation that was identified as a JFR hotspot in the prior PR #2075.
   
   ## Testing
   
   - All 452 existing `maven-resolver-util` tests pass
   - The 813-module reproducer that previously OOMed with 512m heap now 
completes in ~20s
   - Both `path` and `classic` resolvers produce identical results on the 
reproducer
   
   _Hermes Agent (Claude Sonnet 4.6) on behalf of Guillaume Nodet_
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to