Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
3.6.1
-
None
-
None
Description
Maven throws StackOverflowError when version ranges are unsolvable and the dependency graph contains a cycle.
$ mvn install
...
[INFO] --------------------------< suztomo:module-c >--------------------------
[INFO] Building module-c 1.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.406 s
[INFO] Finished at: 2019-08-16T12:10:30-04:00
[INFO] ------------------------------------------------------------------------
...
Exception in thread "main" java.lang.StackOverflowError
at org.eclipse.aether.graph.DefaultDependencyNode.accept(DefaultDependencyNode.java:341)
at org.eclipse.aether.graph.DefaultDependencyNode.accept(DefaultDependencyNode.java:345)
at org.eclipse.aether.graph.DefaultDependencyNode.accept(DefaultDependencyNode.java:345)
at org.eclipse.aether.graph.DefaultDependencyNode.accept(DefaultDependencyNode.java:345)
at org.eclipse.aether.graph.DefaultDependencyNode.accept(DefaultDependencyNode.java:345)
at org.eclipse.aether.graph.DefaultDependencyNode.accept(DefaultDependencyNode.java:345)
...(omitting many lines)...
Example
Example project to reproduce the issue: https://github.com/suztomo/maven-cyclic-dependency-with-range
Diagnosis
In the example above, because of a version conflict on grpc-core (1.21.0 v.s. 1.16.1), org.eclipse.aether.util.graph.transformer.NearestVersionSelector.newFailure tries to throw UnsolvableVersionConflictExceptoin. However, before throwing the exception PathRecordingDependencyVisitor visits nodes in the dependency graph and the graph contains a cycle. The visitor goes to infinite recursion in visiting the cyclic path, resulting in StackOverflowError.
private UnsolvableVersionConflictException newFailure( final ConflictContext context ) { ... PathRecordingDependencyVisitor visitor = new PathRecordingDependencyVisitor( filter ); context.getRoot().accept( visitor ); return new UnsolvableVersionConflictException( visitor.getPaths() ); }
The cycle in the graph consists of module-a and module-b as illustrated below:
module-c:1.0.0 +- module-b:2.0.0 +- module-a:1.0.0 +- module-b:0.0.1 +- module-b:1.0.0 | +- module-a:1.0.0 | +- module-b:0.0.1 | +- module-b:1.0.0 ...
Attachments
Issue Links
- depends upon
-
MNG-6672 Upgrade Maven Resolver to 1.4.2
- Closed
- relates to
-
MRESOLVER-38 SOE/OOME in DefaultDependencyNode.accept
- Closed
-
MRESOLVER-93 PathRecordingDependencyVisitor to handle 3 cycles
- Closed