mirror of
https://github.com/apache/maven-mvnd.git
synced 2025-09-10 13:15:27 +00:00
@@ -36,8 +36,6 @@ import java.util.Scanner;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.apache.maven.shared.utils.StringUtils;
|
||||
import org.mvndaemon.mvnd.common.DaemonCompatibilitySpec;
|
||||
import org.mvndaemon.mvnd.common.DaemonCompatibilitySpec.Result;
|
||||
import org.mvndaemon.mvnd.common.DaemonConnection;
|
||||
@@ -348,15 +346,6 @@ public class DaemonConnector {
|
||||
}
|
||||
}
|
||||
}
|
||||
// .mvn/jvm.config
|
||||
if (Files.isRegularFile(parameters.jvmConfigPath())) {
|
||||
try (Stream<String> lines = Files.lines(parameters.jvmConfigPath())) {
|
||||
lines.flatMap(l -> Stream.of(l.split(" ")))
|
||||
.map(String::trim)
|
||||
.filter(StringUtils::isNotEmpty)
|
||||
.forEach(args::add);
|
||||
}
|
||||
}
|
||||
// memory
|
||||
String minHeapSize = parameters.minHeapSize();
|
||||
if (minHeapSize != null) {
|
||||
|
@@ -168,6 +168,11 @@ public class DaemonParameters {
|
||||
.asPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* The content of the <code>.mvn/jvm.config</code> file will be read
|
||||
* and used as arguments when starting a daemon JVM.
|
||||
* See {@link Environment#MVND_JVM_ARGS}.
|
||||
*/
|
||||
public Path jvmConfigPath() {
|
||||
return multiModuleProjectDirectory().resolve(".mvn/jvm.config");
|
||||
}
|
||||
@@ -311,9 +316,16 @@ public class DaemonParameters {
|
||||
return derive(b -> b.put(Environment.USER_DIR, newUserDir));
|
||||
}
|
||||
|
||||
public DaemonParameters withJdkJavaOpts(String opts) {
|
||||
public DaemonParameters withJdkJavaOpts(String opts, boolean before) {
|
||||
String org = this.properties.getOrDefault(Environment.JDK_JAVA_OPTIONS.getProperty(), "");
|
||||
return derive(b -> b.put(Environment.JDK_JAVA_OPTIONS, org + opts));
|
||||
return derive(b -> b.put(Environment.JDK_JAVA_OPTIONS,
|
||||
org.isEmpty() ? opts : before ? opts + " " + org : org + " " + opts));
|
||||
}
|
||||
|
||||
public DaemonParameters withJvmArgs(String opts, boolean before) {
|
||||
String org = this.properties.getOrDefault(Environment.MVND_JVM_ARGS.getProperty(), "");
|
||||
return derive(b -> b.put(Environment.MVND_JVM_ARGS,
|
||||
org.isEmpty() ? opts : before ? opts + " " + org : org + " " + opts));
|
||||
}
|
||||
|
||||
protected DaemonParameters derive(Consumer<PropertiesBuilder> customizer) {
|
||||
|
@@ -33,6 +33,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.fusesource.jansi.Ansi;
|
||||
import org.fusesource.jansi.internal.CLibrary;
|
||||
@@ -114,6 +115,14 @@ public class DefaultClient implements Client {
|
||||
|
||||
System.setProperty(Environment.MVND_HOME.getProperty(), parameters.mvndHome().toString());
|
||||
|
||||
// .mvn/jvm.config
|
||||
if (Files.isRegularFile(parameters.jvmConfigPath())) {
|
||||
try (Stream<String> jvmArgs = Files.lines(parameters.jvmConfigPath())) {
|
||||
String jvmArgsStr = jvmArgs.collect(Collectors.joining(" "));
|
||||
parameters = parameters.withJvmArgs(jvmArgsStr, false);
|
||||
}
|
||||
}
|
||||
|
||||
int exitCode = 0;
|
||||
boolean noBuffering = batchMode || parameters.noBuffering();
|
||||
try (TerminalOutput output = new TerminalOutput(noBuffering, parameters.rollingWindowSize(), logFile)) {
|
||||
@@ -151,11 +160,12 @@ public class DefaultClient implements Client {
|
||||
public DefaultClient(DaemonParameters parameters) {
|
||||
// Those options are needed in order to be able to set the environment correctly
|
||||
this.parameters = parameters.withJdkJavaOpts(
|
||||
" --add-opens java.base/java.io=ALL-UNNAMED"
|
||||
+ " --add-opens java.base/java.lang=ALL-UNNAMED"
|
||||
+ " --add-opens java.base/java.util=ALL-UNNAMED"
|
||||
+ " --add-opens java.base/sun.net.www.protocol.jar=ALL-UNNAMED"
|
||||
+ " --add-opens java.base/sun.nio.fs=ALL-UNNAMED");
|
||||
"--add-opens java.base/java.io=ALL-UNNAMED "
|
||||
+ "--add-opens java.base/java.lang=ALL-UNNAMED "
|
||||
+ "--add-opens java.base/java.util=ALL-UNNAMED "
|
||||
+ "--add-opens java.base/sun.net.www.protocol.jar=ALL-UNNAMED "
|
||||
+ "--add-opens java.base/sun.nio.fs=ALL-UNNAMED",
|
||||
true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -185,35 +185,41 @@ public enum Environment {
|
||||
*/
|
||||
MVND_THREADS("mvnd.threads", null, null, OptionType.STRING, Flags.NONE, "mvn:-T", "mvn:--threads"),
|
||||
/**
|
||||
* The builder implementation the daemon should use
|
||||
* The builder implementation the daemon should use.
|
||||
*/
|
||||
MVND_BUILDER("mvnd.builder", null, "smart", OptionType.STRING, Flags.NONE, "mvn:-b", "mvn:--builder"),
|
||||
/**
|
||||
* An ID for a newly started daemon
|
||||
* An ID for a newly started daemon.
|
||||
*/
|
||||
MVND_ID("mvnd.id", null, null, OptionType.STRING, Flags.INTERNAL),
|
||||
/**
|
||||
* Internal option to specify the maven extension classpath
|
||||
* Internal option to specify the maven extension classpath.
|
||||
*/
|
||||
MVND_EXT_CLASSPATH("mvnd.extClasspath", null, null, OptionType.STRING, Flags.DISCRIMINATING | Flags.INTERNAL),
|
||||
/**
|
||||
* Internal option to specify the list of maven extension to register
|
||||
* Internal option to specify the list of maven extension to register.
|
||||
*/
|
||||
MVND_CORE_EXTENSIONS("mvnd.coreExtensions", null, null, OptionType.STRING, Flags.DISCRIMINATING | Flags.INTERNAL),
|
||||
/**
|
||||
* The <code>-Xms</code> value to pass to the daemon
|
||||
* The <code>-Xms</code> value to pass to the daemon.
|
||||
* This option takes precedence over options specified in {@link #MVND_JVM_ARGS}.
|
||||
*/
|
||||
MVND_MIN_HEAP_SIZE("mvnd.minHeapSize", null, "128M", OptionType.MEMORY_SIZE, Flags.DISCRIMINATING),
|
||||
/**
|
||||
* The <code>-Xmx</code> value to pass to the daemon
|
||||
* The <code>-Xmx</code> value to pass to the daemon.
|
||||
* This option takes precedence over options specified in {@link #MVND_JVM_ARGS}.
|
||||
*/
|
||||
MVND_MAX_HEAP_SIZE("mvnd.maxHeapSize", null, "2G", OptionType.MEMORY_SIZE, Flags.DISCRIMINATING),
|
||||
/**
|
||||
* The <code>-Xss</code> value to pass to the daemon
|
||||
* The <code>-Xss</code> value to pass to the daemon.
|
||||
* This option takes precedence over options specified in {@link #MVND_JVM_ARGS}.
|
||||
*/
|
||||
MVND_THREAD_STACK_SIZE("mvnd.threadStackSize", null, "1M", OptionType.MEMORY_SIZE, Flags.DISCRIMINATING),
|
||||
/**
|
||||
* Additional JVM args to pass to the daemon
|
||||
* Additional JVM args to pass to the daemon.
|
||||
* The content of the <code>.mvn/jvm.config</code> file will prepended (and thus with
|
||||
* a lesser priority) to the user supplied value for this parameter before being used
|
||||
* as startup options for the daemon JVM.
|
||||
*/
|
||||
MVND_JVM_ARGS("mvnd.jvmArgs", null, null, OptionType.STRING, Flags.DISCRIMINATING | Flags.OPTIONAL),
|
||||
/**
|
||||
|
@@ -394,7 +394,7 @@ public class DaemonMavenCli {
|
||||
|
||||
// redirect stdout and stderr to file
|
||||
try {
|
||||
PrintStream ps = new PrintStream(new FileOutputStream(logFile));
|
||||
PrintStream ps = new PrintStream(new FileOutputStream(logFile), true);
|
||||
System.setOut(ps);
|
||||
System.setErr(ps);
|
||||
} catch (FileNotFoundException e) {
|
||||
|
@@ -78,7 +78,7 @@ public class LoggingOutputStream extends FilterOutputStream {
|
||||
|
||||
public static class LoggingPrintStream extends PrintStream {
|
||||
public LoggingPrintStream(LoggingOutputStream out) {
|
||||
super(out);
|
||||
super(out, true);
|
||||
}
|
||||
|
||||
public void forceFlush() {
|
||||
|
9
dist/src/main/distro/bin/mvnd.cmd
vendored
9
dist/src/main/distro/bin/mvnd.cmd
vendored
@@ -160,15 +160,6 @@ cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
set "jvmConfig=\.mvn\jvm.config"
|
||||
if not exist "%MAVEN_PROJECTBASEDIR%%jvmConfig%" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for %%i in ("%MVND_HOME%"\mvn\boot\*.jar "%MVND_HOME%"\mvn\lib\ext\*.jar "%MVND_HOME%"\mvn\lib\*.jar) do set DAEMON_JAR=!DAEMON_JAR!;%%i
|
||||
@endlocal & set DAEMON_JAR="%DAEMON_JAR%"
|
||||
|
1
dist/src/main/distro/bin/mvnd.sh
vendored
1
dist/src/main/distro/bin/mvnd.sh
vendored
@@ -173,7 +173,6 @@ concat_lines() {
|
||||
}
|
||||
|
||||
MAVEN_PROJECTBASEDIR="${MAVEN_BASEDIR:-`find_maven_basedir "$@"`}"
|
||||
MAVEN_OPTS="`concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config"` $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch project base directory path to Windows format before
|
||||
# executing Maven otherwise this will cause Maven not to consider it.
|
||||
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2019-2022 the original author or authors.
|
||||
*
|
||||
* Licensed 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.mvndaemon.mvnd.it;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mvndaemon.mvnd.assertj.TestClientOutput;
|
||||
import org.mvndaemon.mvnd.client.Client;
|
||||
import org.mvndaemon.mvnd.client.DaemonParameters;
|
||||
import org.mvndaemon.mvnd.junit.MvndNativeTest;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@MvndNativeTest(projectDir = "src/test/projects/jvm-config")
|
||||
public class JvmConfigNativeIT {
|
||||
|
||||
@Inject
|
||||
Client client;
|
||||
|
||||
@Inject
|
||||
DaemonParameters parameters;
|
||||
|
||||
@Test
|
||||
void version() throws IOException, InterruptedException {
|
||||
final TestClientOutput o = new TestClientOutput();
|
||||
client.execute(o, "org.codehaus.gmaven:groovy-maven-plugin:2.1.1:execute",
|
||||
"-Dsource=System.out.println(java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments())")
|
||||
.assertSuccess();
|
||||
String xmx = "-Xmx512k";
|
||||
assertTrue(o.getMessages().stream()
|
||||
.anyMatch(m -> m.toString().contains(xmx)), "Output should contain " + xmx + " but is:\n"
|
||||
+ o.getMessages().stream().map(Object::toString).collect(Collectors.joining("\n")));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1 @@
|
||||
-Xmx512k
|
@@ -0,0 +1,3 @@
|
||||
-Dmaven.wagon.httpconnectionManager.ttlSeconds=120
|
||||
-Dmaven.wagon.http.retryHandler.requestSentEnabled=true
|
||||
-Dmaven.wagon.http.retryHandler.count=10
|
27
integration-tests/src/test/projects/jvm-config/pom.xml
Normal file
27
integration-tests/src/test/projects/jvm-config/pom.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<!--
|
||||
|
||||
Copyright 2021 the original author or authors.
|
||||
|
||||
Licensed 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.
|
||||
|
||||
-->
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
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>org.mvndaemon.mvnd.test.jvm-config</groupId>
|
||||
<artifactId>jvm-config</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
</project>
|
1
pom.xml
1
pom.xml
@@ -309,6 +309,7 @@ limitations under the License.</inlineHeader>
|
||||
<exclude>**/m2.conf</exclude>
|
||||
<exclude>**/mvnd</exclude>
|
||||
<exclude>**/.mvn/maven.config</exclude>
|
||||
<exclude>**/.mvn/jvm.config</exclude>
|
||||
<exclude>.gitattributes/</exclude>
|
||||
<exclude>.mvn/maven.config</exclude>
|
||||
<exclude>.mvn/wrapper/</exclude>
|
||||
|
Reference in New Issue
Block a user