Постановка задачи
У меня есть агрегатор POM, родительский POM которого также является одним из его дочерних модулей. Когда я запускаю многопоточную сборку Maven с обычными целями (например, mvn clean install -T 2
), она работает так, как ожидалось: сначала строится родительский модуль, а затем агрегатор.
Однако при запуске mvn sonar:sonar -T 2
сборка зависает на неопределенный срок (с org.sonarsource.scanner.maven:sonar-maven-plugin:3.4.0.905
).
Пример проекта
Макет:
sample/
- parent/
- pom.xml
- pom.xml
Агрегатор POM (sample/pom.xml):
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.sample</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>parent/pom.xml</relativePath>
</parent>
<artifactId>aggregator</artifactId>
<packaging>pom</packaging>
<modules>
<module>parent</module>
</modules>
</project>
Родительский POM (образец/родитель/pom.xml):
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.4.0.905</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Журналы сборки
Обычная многопоточная сборка работает как положено: mvn clean install -T 2
DANIJOH2-M-C5DB:deadlock-sample danijoh2$ mvn clean install -T 2
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] parent [pom]
[INFO] aggregator [pom]
[INFO]
[INFO] Using the MultiThreadedBuilder implementation with a thread count of 2
[INFO]
[INFO] -------------------------< com.sample:parent >--------------------------
[INFO] Building parent 1.0.0-SNAPSHOT [1/2]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ parent ---
[INFO] Deleting /Users/danijoh2/Desktop/deadlock-sample/parent/target
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ parent ---
[INFO] Installing /Users/danijoh2/Desktop/deadlock-sample/parent/pom.xml to /Users/danijoh2/.m2/repository/com/sample/parent/1.0.0-SNAPSHOT/parent-1.0.0-SNAPSHOT.pom
[INFO]
[INFO] -----------------------< com.sample:aggregator >------------------------
[INFO] Building aggregator 1.0.0-SNAPSHOT [2/2]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ aggregator ---
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ aggregator ---
[INFO] Installing /Users/danijoh2/Desktop/deadlock-sample/pom.xml to /Users/danijoh2/.m2/repository/com/sample/aggregator/1.0.0-SNAPSHOT/aggregator-1.0.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] parent ............................................. SUCCESS [ 0.805 s]
[INFO] aggregator 1.0.0-SNAPSHOT .......................... SUCCESS [ 0.024 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.984 s (Wall Clock)
[INFO] Finished at: 2018-04-17T08:15:31-07:00
[INFO] ------------------------------------------------------------------------
Но при запуске sonar target зависает на неопределенное время: mvn sonar:sonar -T 2
(Также можно воспроизвести с mvn clean install sonar:sonar -T 2
, в этом случае зависает сразу после сборки и установки обоих проектов)
DANIJOH2-M-C5DB:deadlock-sample danijoh2$ mvn sonar:sonar -T 2
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] parent [pom]
[INFO] aggregator [pom]
[INFO]
[INFO] Using the MultiThreadedBuilder implementation with a thread count of 2
<process is now hung>
Запуск той же сборки с одним потоком работает нормально: mvn sonar:sonar
DANIJOH2-M-C5DB:deadlock-sample danijoh2$ mvn sonar:sonar
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] parent [pom]
[INFO] aggregator [pom]
[INFO]
[INFO] -----------------------< com.sample:aggregator >------------------------
[INFO] Building aggregator 1.0.0-SNAPSHOT [1/2]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- sonar-maven-plugin:3.4.0.905:sonar (default-cli) @ aggregator ---
...
[INFO] ANALYSIS SUCCESSFUL, you can browse http://localhost:9000/dashboard/index/com.sample:aggregator
[INFO] Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report
[INFO] More about the report processing at http://localhost:9000/api/ce/task?id=AWLUPrWVbruNGPzM1Q9P
[INFO] Task total time: 11.792 s
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] parent ............................................. SKIPPED
[INFO] aggregator 1.0.0-SNAPSHOT .......................... SUCCESS [ 16.700 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 18.462 s
[INFO] Finished at: 2018-04-17T08:35:01-07:00
[INFO] ------------------------------------------------------------------------
Трассировка стека зависшего процесса Maven
2018-04-17 08:25:33
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.152-b16 mixed mode):
"Attach Listener" #11 daemon prio=9 os_prio=31 tid=0x00007fcf4d22e800 nid=0x2807 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Service Thread" #8 daemon prio=9 os_prio=31 tid=0x00007fcf4982c000 nid=0x3703 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C1 CompilerThread2" #7 daemon prio=9 os_prio=31 tid=0x00007fcf4b03a800 nid=0x4503 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" #6 daemon prio=9 os_prio=31 tid=0x00007fcf4b039800 nid=0x3403 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" #5 daemon prio=9 os_prio=31 tid=0x00007fcf49832000 nid=0x4703 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x00007fcf49817000 nid=0x3207 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007fcf4a809800 nid=0x5003 in Object.wait() [0x0000700004411000] java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000782098a08> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x0000000782098a08> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
"Reference Handler" #2 daemon prio=10 os_prio=31 tid=0x00007fcf4a807000 nid=0x2d03 in Object.wait() [0x000070000430e000] java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000782098bc0> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x0000000782098bc0> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"main" #1 prio=5 os_prio=31 tid=0x00007fcf4a006000 nid=0x1a03 waiting on condition [0x0000700003cfb000] java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x0000000781595778> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at java.util.concurrent.ExecutorCompletionService.take(ExecutorCompletionService.java:193)
at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder.multiThreadedProjectTaskSegmentBuild(MultiThreadedBuilder.java:140)
at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder.build(MultiThreadedBuilder.java:101)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:956)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:290)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:194)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
"VM Thread" os_prio=31 tid=0x00007fcf4b01c000 nid=0x5203 runnable
"GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007fcf4a00f000 nid=0x2007 runnable
"GC task thread#1 (ParallelGC)" os_prio=31 tid=0x00007fcf49800800 nid=0x1f03 runnable
"GC task thread#2 (ParallelGC)" os_prio=31 tid=0x00007fcf4a010000 nid=0x2a03 runnable
"GC task thread#3 (ParallelGC)" os_prio=31 tid=0x00007fcf4a010800 nid=0x5303 runnable
"VM Periodic Task Thread" os_prio=31 tid=0x00007fcf49810800 nid=0x4303 waiting on condition
JNI global references: 229
Сведения о машине
DANIJOH2-M-C5DB:deadlock-sample danijoh2$ mvn --version
Apache Maven 3.5.3 (3383c37e1f9e9b3bc3df5050c29c8aff9f295297; 2018-02-24T11:49:05-08:00)
Maven home: /Users/danijoh2/Work/maven-3.5.3
Java version: 1.8.0_152, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_152.jdk/Contents/Home/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "10.13.4", arch: "x86_64", family: "mac"
Резюме
Я видел такое же поведение с Maven 3.0.5, 3.2.3, 3.3.9. Я также пробовал использовать sonar-maven-plugin 3.0 и 3.3.0.603 с теми же результатами.
В нашем проекте с ~100 модулями многопоточность сокращает время сборки с ~30 минут до ‹10 минут. Если я сделаю сам агрегатор родительским (и полностью избавлюсь от родительского модуля), то он будет работать нормально. Проблема с этим подходом заключается в том, что мы также создаем агрегированные отчеты по сайту для нашего проекта, когда они не будут работать должным образом, поскольку POM агрегатора будет построен перед его модулями. Я вижу еще две альтернативы:
- Запустите
sonar:sonar
в качестве специального шага после запускаclean install -T 2
в проекте. - Настройте автономное задание для сборки и выпуска родительской POM и укажите версию выпуска в агрегаторе.
На данный момент я выберу первый подход, но хотел бы увидеть цель sonar:sonar
, чтобы иметь возможность обрабатывать этот сценарий в будущем.