You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/10/15 07:17:13 UTC
(maven) branch maven-4.0.x updated: [Backport maven-4.0.x] Fix #13405: Do not capture JVM stderr notices into jvm.config options (#13530)
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch maven-4.0.x
in repository https://gitbox.apache.org/repos/asf/maven.git
The following commit(s) were added to refs/heads/maven-4.0.x by this push:
new 2dacffff2b [Backport maven-4.0.x] Fix #13405: Do not capture JVM stderr notices into jvm.config options (#13530)
2dacffff2b is described below
commit 2dacffff2b2640179305bb0da7ad180fbcbd430c
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Thu Oct 15 09:17:07 2026 +0200
[Backport maven-4.0.x] Fix #13405: Do not capture JVM stderr notices into jvm.config options (#13530)
- Separate stdout from stderr in bin/mvn when executing JvmConfigParser.java
- Redirect stderr to a temporary file; display it only on non-zero exit to avoid polluting MAVEN_OPTS with JVM tool notices (JAVA_TOOL_OPTIONS, JDK_JAVA_OPTIONS, _JAVA_OPTIONS)
- Add test-mvn-jvm-config.sh to verify JVM notices do not pollute JVM arguments and parser errors are still reported
- Register the test script in the shell-script-tests profile in apache-maven/pom.xml
Backport of #13447
Co-authored-by: Yashi Singhal <ya...@gmail.com>
---
apache-maven/pom.xml | 14 ++
apache-maven/src/assembly/maven/bin/mvn | 36 +++-
.../src/test/scripts/test-mvn-jvm-config.sh | 190 +++++++++++++++++++++
3 files changed, 233 insertions(+), 7 deletions(-)
diff --git a/apache-maven/pom.xml b/apache-maven/pom.xml
index 21ec647e2c..8d811a6899 100644
--- a/apache-maven/pom.xml
+++ b/apache-maven/pom.xml
@@ -492,6 +492,20 @@ under the License.
</arguments>
</configuration>
</execution>
+ <execution>
+ <id>test-mvn-jvm-config</id>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <phase>test</phase>
+ <configuration>
+ <skip>${skipTests}</skip>
+ <executable>sh</executable>
+ <arguments>
+ <argument>${project.basedir}/src/test/scripts/test-mvn-jvm-config.sh</argument>
+ </arguments>
+ </configuration>
+ </execution>
</executions>
</plugin>
</plugins>
diff --git a/apache-maven/src/assembly/maven/bin/mvn b/apache-maven/src/assembly/maven/bin/mvn
index 15e899f678..4727dbf63e 100755
--- a/apache-maven/src/assembly/maven/bin/mvn
+++ b/apache-maven/src/assembly/maven/bin/mvn
@@ -221,26 +221,48 @@ concat_lines() {
}
# Run the parser
- # Capture both stdout and stderr for comprehensive error reporting
- parser_output=$("$JAVACMD" -cp "$MAVEN_HOME/bin" JvmConfigParser "$1" "$_basedir_native" 2>&1)
+ # Capture stdout for JVM options; capture stderr separately so JVM notices
+ # (e.g. JAVA_TOOL_OPTIONS) do not pollute MAVEN_OPTS.
+ parser_stderr_file=$(mktemp "${TMPDIR:-/tmp}/mvn-jvm-config-stderr.XXXXXX" 2>/dev/null || echo "${TMPDIR:-/tmp}/mvn-jvm-config-stderr.$$")
+ trap 'rm -f "$parser_stderr_file"' EXIT INT TERM
+ parser_output=$("$JAVACMD" -cp "$MAVEN_HOME/bin" JvmConfigParser "$1" "$_basedir_native" 2>"$parser_stderr_file")
parser_exit=$?
if [ -n "$MAVEN_DEBUG_SCRIPT" ]; then
echo "[DEBUG] JvmConfigParser exit code: $parser_exit" >&2
printf '[DEBUG] JvmConfigParser output: %s\n' "$parser_output" >&2
+ if [ -s "$parser_stderr_file" ]; then
+ while IFS= read -r parser_err_line || [ -n "$parser_err_line" ]; do
+ printf '[DEBUG] JvmConfigParser stderr: %s\n' "$parser_err_line" >&2
+ done < "$parser_stderr_file"
+ fi
fi
if [ $parser_exit -ne 0 ]; then
# Parser failed - print comprehensive error information
echo "ERROR: JvmConfigParser failed with exit code $parser_exit" >&2
- echo " jvm.config path: $1" >&2
- echo " Maven basedir: $MAVEN_PROJECTBASEDIR" >&2
- echo " Java command: $JAVACMD" >&2
- printf ' Parser output:\n' >&2
- printf '%s\n' "$parser_output" | sed 's/^/ /' >&2
+ printf ' jvm.config path: %s\n' "$1" >&2
+ printf ' Maven basedir: %s\n' "$MAVEN_PROJECTBASEDIR" >&2
+ printf ' Java command: %s\n' "$JAVACMD" >&2
+ echo " Parser output:" >&2
+ # Print captured stderr (parser exceptions/diagnostics) and stdout so no diagnostic info is dropped
+ if [ -s "$parser_stderr_file" ]; then
+ while IFS= read -r parser_err_line || [ -n "$parser_err_line" ]; do
+ printf ' %s\n' "$parser_err_line" >&2
+ done < "$parser_stderr_file"
+ fi
+ if [ -n "$parser_output" ]; then
+ printf '%s\n' "$parser_output" | while IFS= read -r parser_out_line || [ -n "$parser_out_line" ]; do
+ printf ' %s\n' "$parser_out_line" >&2
+ done
+ fi
+ rm -f "$parser_stderr_file" 2>/dev/null || :
+ trap - EXIT INT TERM
exit 1
fi
+ rm -f "$parser_stderr_file" 2>/dev/null || :
+ trap - EXIT INT TERM
printf '%s\n' "$parser_output"
fi
}
diff --git a/apache-maven/src/test/scripts/test-mvn-jvm-config.sh b/apache-maven/src/test/scripts/test-mvn-jvm-config.sh
new file mode 100644
index 0000000000..f4a95f2657
--- /dev/null
+++ b/apache-maven/src/test/scripts/test-mvn-jvm-config.sh
@@ -0,0 +1,190 @@
+#!/bin/sh
+
+# 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.
+
+# -----------------------------------------------------------------------------
+# Tests that JVM options from .mvn/jvm.config are correctly parsed and that
+# JVM notices printed to stderr (e.g. JAVA_TOOL_OPTIONS, JDK_JAVA_OPTIONS,
+# _JAVA_OPTIONS) do not pollute MAVEN_OPTS.
+#
+# Usage: sh apache-maven/src/test/scripts/test-mvn-jvm-config.sh
+# -----------------------------------------------------------------------------
+
+set -e
+
+script_dir=`cd "\`dirname "$0"\`" && pwd`
+mvn_script="$script_dir/../../assembly/maven/bin/mvn"
+
+if [ ! -f "$mvn_script" ]; then
+ echo "Cannot locate the mvn script at $mvn_script" >&2
+ exit 1
+fi
+
+sh_bin=`unset -f command; command -v sh`
+
+work_dir=`mktemp -d "${TMPDIR:-/tmp}/mvn-jvm-config.XXXXXX"`
+work_dir=`cd "$work_dir" && pwd`
+trap 'rm -rf "$work_dir"' EXIT INT TERM
+
+stub_dir="$work_dir/stubs"
+maven_home="$work_dir/maven-home"
+project_dir="$work_dir/project"
+
+mkdir -p "$stub_dir" "$maven_home/bin" "$maven_home/boot" "$project_dir/.mvn"
+
+cp "$mvn_script" "$maven_home/bin/mvn"
+touch "$maven_home/bin/m2.conf" "$maven_home/boot/plexus-classworlds-9.9.9.jar"
+
+# uname stub
+cat > "$stub_dir/uname" <<'STUB'
+#!/bin/sh
+echo "Linux"
+STUB
+
+# dirname stub
+cat > "$stub_dir/dirname" <<'STUB'
+#!/bin/sh
+path="$1"
+case "$path" in
+ */*)
+ path="${path%/*}"
+ [ -n "$path" ] || path="/"
+ ;;
+ *) path="." ;;
+esac
+printf '%s\n' "$path"
+STUB
+
+# java stub: simulates Java runtime notices on stderr when tool options env vars are set
+cat > "$stub_dir/java" <<'STUB'
+#!/bin/sh
+
+# If tool options are set, print JVM notices on stderr just like real JDK
+if [ -n "$JAVA_TOOL_OPTIONS" ]; then
+ echo "Picked up JAVA_TOOL_OPTIONS: $JAVA_TOOL_OPTIONS" >&2
+fi
+if [ -n "$JDK_JAVA_OPTIONS" ]; then
+ echo "NOTE: Picked up JDK_JAVA_OPTIONS: $JDK_JAVA_OPTIONS" >&2
+fi
+if [ -n "$_JAVA_OPTIONS" ]; then
+ echo "Picked up _JAVA_OPTIONS: $_JAVA_OPTIONS" >&2
+fi
+
+case " $* " in
+ *" -version "*) exit 0 ;;
+esac
+
+case "$3" in
+ JvmConfigParser)
+ if [ "$FAIL_PARSER" = "1" ]; then
+ echo "Error: simulated parser failure" >&2
+ exit 1
+ fi
+ # Emulate JvmConfigParser output; args are: -cp <bin-dir> JvmConfigParser <config> <basedir>
+ while IFS= read -r line || [ -n "$line" ]; do
+ line="${line%%#*}"
+ for token in $line; do
+ printf '"%s" ' "$token"
+ done
+ done < "$4"
+ printf '\n'
+ exit 0 ;;
+esac
+
+# For the main launch, echo all arguments bracketed
+for arg in "$@"; do printf '[%s]' "$arg"; done
+printf '\n'
+STUB
+
+chmod +x "$stub_dir/uname" "$stub_dir/dirname" "$stub_dir/java" "$maven_home/bin/mvn"
+
+echo '-Xmx512m -Dcustom.prop=hello' > "$project_dir/.mvn/jvm.config"
+
+failures=0
+
+assert_contains() {
+ desc="$1"; haystack="$2"; needle="$3"
+ case "$haystack" in
+ *"$needle"*) printf 'ok - %s\n' "$desc" ;;
+ *)
+ printf 'FAILED - %s\n' "$desc"
+ printf ' expected to contain: %s\n' "$needle"
+ printf ' actual: %s\n' "$haystack"
+ failures=`expr "$failures" + 1`
+ ;;
+ esac
+}
+
+assert_not_contains() {
+ desc="$1"; haystack="$2"; needle="$3"
+ case "$haystack" in
+ *"$needle"*)
+ printf 'FAILED - %s\n' "$desc"
+ printf ' expected NOT to contain: %s\n' "$needle"
+ printf ' actual: %s\n' "$haystack"
+ failures=`expr "$failures" + 1`
+ ;;
+ *) printf 'ok - %s\n' "$desc" ;;
+ esac
+}
+
+run_mvn() {
+ ( cd "$project_dir" &&
+ PATH="$stub_dir" JAVA_HOME= MAVEN_SKIP_RC=1 \
+ "$sh_bin" "$maven_home/bin/mvn" validate 2>/dev/null )
+}
+
+run_mvn_stderr() {
+ ( cd "$project_dir" &&
+ PATH="$stub_dir" JAVA_HOME= MAVEN_SKIP_RC=1 \
+ "$sh_bin" "$maven_home/bin/mvn" validate 2>&1 >/dev/null )
+}
+
+# Test 1: Clean environment - JVM options from jvm.config are present
+out=`run_mvn`
+assert_contains "clean env: jvm.config options present" "$out" "[-Xmx512m]"
+assert_contains "clean env: custom prop present" "$out" "[-Dcustom.prop=hello]"
+
+# Test 2: JAVA_TOOL_OPTIONS is set
+out=`JAVA_TOOL_OPTIONS="-Dfoo=bar" run_mvn`
+assert_contains "JAVA_TOOL_OPTIONS: jvm.config options present" "$out" "[-Xmx512m]"
+assert_not_contains "JAVA_TOOL_OPTIONS: 'Picked' not in args" "$out" "[Picked]"
+assert_not_contains "JAVA_TOOL_OPTIONS: 'up' not in args" "$out" "[up]"
+assert_not_contains "JAVA_TOOL_OPTIONS: 'JAVA_TOOL_OPTIONS:' not in args" "$out" "[JAVA_TOOL_OPTIONS:]"
+
+# Test 3: JDK_JAVA_OPTIONS is set
+out=`JDK_JAVA_OPTIONS="-Dfoo=bar" run_mvn`
+assert_contains "JDK_JAVA_OPTIONS: jvm.config options present" "$out" "[-Xmx512m]"
+assert_not_contains "JDK_JAVA_OPTIONS: 'NOTE:' not in args" "$out" "[NOTE:]"
+
+# Test 4: _JAVA_OPTIONS is set
+out=`_JAVA_OPTIONS="-Dfoo=bar" run_mvn`
+assert_contains "_JAVA_OPTIONS: jvm.config options present" "$out" "[-Xmx512m]"
+assert_not_contains "_JAVA_OPTIONS: 'Picked' not in args" "$out" "[Picked]"
+
+# Test 5: Parser failure displays stderr output
+err_out=`FAIL_PARSER=1 run_mvn_stderr || true`
+assert_contains "parser failure: error message displayed" "$err_out" "ERROR: JvmConfigParser failed with exit code 1"
+assert_contains "parser failure: parser stderr displayed" "$err_out" "simulated parser failure"
+
+if [ "$failures" -ne 0 ]; then
+ printf '%s assertion(s) failed\n' "$failures"
+ exit 1
+fi
+
+echo "All assertions passed"