From 4f0b06be837aaf277fd7d9e169df43ee536abfbe Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Mon, 17 Nov 2025 11:24:05 +0100 Subject: [PATCH 1/3] Maven Resolver lockrepro --- ...ResolveTransitiveDependenciesParallel.java | 209 ++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/ResolveTransitiveDependenciesParallel.java diff --git a/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/ResolveTransitiveDependenciesParallel.java b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/ResolveTransitiveDependenciesParallel.java new file mode 100644 index 000000000..b21eb7f75 --- /dev/null +++ b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/ResolveTransitiveDependenciesParallel.java @@ -0,0 +1,209 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.maven.resolver.examples; + +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.maven.resolver.examples.util.Booter; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.RepositorySystemSession.CloseableSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.resolution.ArtifactResult; +import org.eclipse.aether.resolution.DependencyRequest; +import org.eclipse.aether.util.artifact.JavaScopes; + +/** + * Resolves the transitive (compile) dependencies of an artifact. + */ +public class ResolveTransitiveDependenciesParallel { + + /** + * Main. + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + System.out.println("------------------------------------------------------------"); + System.out.println(ResolveTransitiveDependenciesParallel.class.getSimpleName()); + + try (RepositorySystem system = Booter.newRepositorySystem(Booter.selectFactory(args)); + CloseableSession session = Booter.newRepositorySystemSession(system, Booter.selectFs(args)) + .setTransferListener(null) + .setRepositoryListener(null) + .setConfigProperty("aether.syncContext.named.time", "3") + .build()) { + Artifact bigArtifact1 = new DefaultArtifact("org.bytedeco:llvm:jar:linux-arm64:16.0.4-1.5.9"); + Artifact bigArtifact2 = new DefaultArtifact("org.bytedeco:llvm:jar:linux-armhf:16.0.4-1.5.9"); + Artifact bigArtifact3 = new DefaultArtifact("org.bytedeco:llvm:jar:linux-ppc64le:16.0.4-1.5.9"); + Artifact bigArtifact4 = new DefaultArtifact("org.bytedeco:llvm:jar:linux-x86:16.0.4-1.5.9"); + Artifact bigArtifact5 = new DefaultArtifact("org.bytedeco:llvm:jar:linux-x86_64:16.0.4-1.5.9"); + Artifact bigArtifact6 = new DefaultArtifact("org.bytedeco:llvm:jar:macosx-arm64:16.0.4-1.5.9"); + Artifact bigArtifact7 = new DefaultArtifact("org.bytedeco:llvm:jar:macosx-x86_64:16.0.4-1.5.9"); + Artifact bigArtifact8 = new DefaultArtifact("org.bytedeco:llvm:jar:windows-x86:16.0.4-1.5.9"); + Artifact bigArtifact9 = new DefaultArtifact("org.bytedeco:llvm:jar:windows-x86_64:16.0.4-1.5.9"); + + CountDownLatch latch = new CountDownLatch(8); + AtomicInteger success = new AtomicInteger(0); + AtomicInteger fail = new AtomicInteger(0); + + Thread thread1 = new Thread(resolveWithDependencies( + latch, + success, + fail, + system, + session, + Booter.newRepositories(system, session), + "org.example:test:1", + bigArtifact1, + bigArtifact2)); + Thread thread2 = new Thread(resolveWithDependencies( + latch, + success, + fail, + system, + session, + Booter.newRepositories(system, session), + "org.example:test:2", + bigArtifact2, + bigArtifact3)); + Thread thread3 = new Thread(resolveWithDependencies( + latch, + success, + fail, + system, + session, + Booter.newRepositories(system, session), + "org.example:test:3", + bigArtifact3, + bigArtifact4)); + Thread thread4 = new Thread(resolveWithDependencies( + latch, + success, + fail, + system, + session, + Booter.newRepositories(system, session), + "org.example:test:4", + bigArtifact4, + bigArtifact5)); + Thread thread5 = new Thread(resolveWithDependencies( + latch, + success, + fail, + system, + session, + Booter.newRepositories(system, session), + "org.example:test:5", + bigArtifact5, + bigArtifact6)); + Thread thread6 = new Thread(resolveWithDependencies( + latch, + success, + fail, + system, + session, + Booter.newRepositories(system, session), + "org.example:test:6", + bigArtifact6, + bigArtifact7)); + Thread thread7 = new Thread(resolveWithDependencies( + latch, + success, + fail, + system, + session, + Booter.newRepositories(system, session), + "org.example:test:7", + bigArtifact7, + bigArtifact8)); + Thread thread8 = new Thread(resolveWithDependencies( + latch, + success, + fail, + system, + session, + Booter.newRepositories(system, session), + "org.example:test:8", + bigArtifact8, + bigArtifact9)); + + thread1.start(); + thread2.start(); + thread3.start(); + thread4.start(); + thread5.start(); + thread6.start(); + thread7.start(); + thread8.start(); + + latch.await(); + + System.out.println("====="); + System.out.println("TOTAL success=" + success.get() + "; fail=" + fail.get()); + } + } + + @SuppressWarnings("checkstyle:parameternumber") + private static Runnable resolveWithDependencies( + CountDownLatch latch, + AtomicInteger success, + AtomicInteger fail, + RepositorySystem system, + RepositorySystemSession session, + List repositories, + String gav, + Artifact... deps) { + return () -> { + try { + CollectRequest collectRequest = new CollectRequest(); + collectRequest.setRootArtifact(new DefaultArtifact(gav)); + for (Artifact dep : deps) { + collectRequest.addDependency(new Dependency(dep, JavaScopes.COMPILE)); + } + collectRequest.setRepositories(repositories); + DependencyRequest dependencyRequest = new DependencyRequest(collectRequest, null); + List artifactResults = + system.resolveDependencies(session, dependencyRequest).getArtifactResults(); + int resolved = 9; + int fails = 0; + for (ArtifactResult artifactResult : artifactResults) { + if (artifactResult.isResolved()) { + resolved++; + } else { + fails++; + } + } + System.out.println("DONE " + gav + ": resolved " + resolved + "; failed " + fails); + success.getAndIncrement(); + } catch (Exception e) { + System.out.println("FAILED " + gav + ": " + e.getMessage()); + fail.getAndIncrement(); + } finally { + latch.countDown(); + } + }; + } +} From 7df8ede093bc8a19a8b053310d9653a3737c5a30 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Mon, 17 Nov 2025 13:34:51 +0100 Subject: [PATCH 2/3] Complete it --- ...ResolveTransitiveDependenciesParallel.java | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/ResolveTransitiveDependenciesParallel.java b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/ResolveTransitiveDependenciesParallel.java index b21eb7f75..8b99d6b04 100644 --- a/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/ResolveTransitiveDependenciesParallel.java +++ b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/ResolveTransitiveDependenciesParallel.java @@ -18,6 +18,9 @@ */ package org.apache.maven.resolver.examples; +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; @@ -36,8 +39,9 @@ import org.eclipse.aether.util.artifact.JavaScopes; /** - * Resolves the transitive (compile) dependencies of an artifact. - */ + * Resolves the transitive (compile) LARGE dependencies of an imaginary artifact in parallel. + * This is the reproducer for locking issues: { try { + Instant now = Instant.now(); CollectRequest collectRequest = new CollectRequest(); collectRequest.setRootArtifact(new DefaultArtifact(gav)); for (Artifact dep : deps) { @@ -196,7 +224,8 @@ private static Runnable resolveWithDependencies( fails++; } } - System.out.println("DONE " + gav + ": resolved " + resolved + "; failed " + fails); + String dur = Duration.between(now, Instant.now()).get(ChronoUnit.SECONDS) + " sec"; + System.out.println("DONE (" + dur + "): " + gav + ": resolved " + resolved + "; failed " + fails); success.getAndIncrement(); } catch (Exception e) { System.out.println("FAILED " + gav + ": " + e.getMessage()); From a00c13fa7eb1f422d756f68604c534915e06d701 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Tue, 18 Nov 2025 20:08:50 +0100 Subject: [PATCH 3/3] Fix this one as well --- .../examples/ResolveTransitiveDependenciesParallel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/ResolveTransitiveDependenciesParallel.java b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/ResolveTransitiveDependenciesParallel.java index 8b99d6b04..cb2ebc81f 100644 --- a/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/ResolveTransitiveDependenciesParallel.java +++ b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/ResolveTransitiveDependenciesParallel.java @@ -215,7 +215,7 @@ private static Runnable resolveWithDependencies( DependencyRequest dependencyRequest = new DependencyRequest(collectRequest, null); List artifactResults = system.resolveDependencies(session, dependencyRequest).getArtifactResults(); - int resolved = 9; + int resolved = 0; int fails = 0; for (ArtifactResult artifactResult : artifactResults) { if (artifactResult.isResolved()) {