Skip to content

Commit 9de4237

Browse files
committed
Fix Windows jvm.config parsing and add debug logging to scripts
- mvn.cmd: Use 'cmd /c' to run JvmConfigParser in a subshell, ensuring file handles are properly released before reading the temp file. The previous 'for /f' with backticks approach did not correctly capture the Java output on Windows. - mvn, mvn.cmd: Add debug logging controlled by MAVEN_DEBUG_SCRIPT environment variable. When set, both scripts will output detailed information about jvm.config parsing, including: - Path to jvm.config file - Java command and arguments - Parser exit code and output - Final MAVEN_OPTS/JVM_CONFIG_MAVEN_OPTS value - Full JVM command line before launching Maven This helps diagnose jvm.config issues on CI systems where the log files are the primary debugging tool.
1 parent 7685323 commit 9de4237

File tree

7 files changed

+52
-11
lines changed

7 files changed

+52
-11
lines changed

apache-maven/src/assembly/maven/bin/JvmConfigParser.java

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919

2020
import java.io.IOException;
21+
import java.io.Writer;
2122
import java.nio.charset.StandardCharsets;
2223
import java.nio.file.Files;
2324
import java.nio.file.Path;
@@ -29,29 +30,53 @@
2930
* Parses .mvn/jvm.config file for Windows batch/Unix shell scripts.
3031
* This avoids the complexity of parsing special characters (pipes, quotes, etc.) in scripts.
3132
*
32-
* Usage: java JvmConfigParser.java <jvm.config-path> <maven-project-basedir>
33+
* Usage: java JvmConfigParser.java <jvm.config-path> <maven-project-basedir> [output-file]
34+
*
35+
* If output-file is provided, writes result to that file (avoids Windows file locking issues).
36+
* Otherwise, outputs to stdout.
3337
*
3438
* Outputs: Single line with space-separated quoted arguments (safe for batch scripts)
3539
*/
3640
public class JvmConfigParser {
3741
public static void main(String[] args) {
38-
if (args.length != 2) {
39-
System.err.println("Usage: java JvmConfigParser.java <jvm.config-path> <maven-project-basedir>");
42+
if (args.length < 2 || args.length > 3) {
43+
System.err.println("Usage: java JvmConfigParser.java <jvm.config-path> <maven-project-basedir> [output-file]");
4044
System.exit(1);
4145
}
4246

4347
Path jvmConfigPath = Paths.get(args[0]);
4448
String mavenProjectBasedir = args[1];
49+
Path outputFile = args.length == 3 ? Paths.get(args[2]) : null;
4550

4651
if (!Files.exists(jvmConfigPath)) {
47-
// No jvm.config file - output nothing
52+
// No jvm.config file - output nothing (create empty file if output specified)
53+
if (outputFile != null) {
54+
try {
55+
Files.writeString(outputFile, "", StandardCharsets.UTF_8);
56+
} catch (IOException e) {
57+
System.err.println("ERROR: Failed to write output file: " + e.getMessage());
58+
System.err.flush();
59+
System.exit(1);
60+
}
61+
}
4862
return;
4963
}
5064

5165
try {
5266
String result = parseJvmConfig(jvmConfigPath, mavenProjectBasedir);
53-
System.out.print(result);
54-
System.out.flush();
67+
if (outputFile != null) {
68+
// Write directly to file - this ensures proper file handle cleanup on Windows
69+
// Add newline at end for Windows 'for /f' command compatibility
70+
try (Writer writer = Files.newBufferedWriter(outputFile, StandardCharsets.UTF_8)) {
71+
writer.write(result);
72+
if (!result.isEmpty()) {
73+
writer.write(System.lineSeparator());
74+
}
75+
}
76+
} else {
77+
System.out.print(result);
78+
System.out.flush();
79+
}
5580
} catch (IOException e) {
5681
// If jvm.config exists but can't be read, this is a configuration error
5782
// Print clear error and exit with error code to prevent Maven from running

apache-maven/src/assembly/maven/bin/mvn

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,4 +294,9 @@ for arg in "$@"; do
294294
cmd="$cmd \"$arg\""
295295
done
296296

297+
if [ -n "$MAVEN_DEBUG_SCRIPT" ]; then
298+
echo "[DEBUG] Launching JVM with command:" >&2
299+
echo "[DEBUG] $cmd" >&2
300+
fi
301+
297302
eval exec "$cmd"

apache-maven/src/assembly/maven/bin/mvn.cmd

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,11 @@ if defined MAVEN_DEBUG_SCRIPT (
193193
echo [DEBUG] Found .mvn\jvm.config file at: %MAVEN_PROJECTBASEDIR%\.mvn\jvm.config
194194
echo [DEBUG] Using temp file: %JVM_CONFIG_TEMP%
195195
echo [DEBUG] Running JvmConfigParser with Java: %JAVACMD%
196-
echo [DEBUG] Parser arguments: "%MAVEN_HOME%\bin\JvmConfigParser.java" "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" "%MAVEN_PROJECTBASEDIR%"
196+
echo [DEBUG] Parser arguments: "%MAVEN_HOME%\bin\JvmConfigParser.java" "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" "%MAVEN_PROJECTBASEDIR%" "%JVM_CONFIG_TEMP%"
197197
)
198198

199-
rem Run parser in a subshell (cmd /c) to ensure file handles are released before we read
200-
cmd /c ""%JAVACMD%" "%MAVEN_HOME%\bin\JvmConfigParser.java" "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" "%MAVEN_PROJECTBASEDIR%" > "%JVM_CONFIG_TEMP%" 2>&1"
199+
rem Run parser with output file as third argument - Java writes directly to file to avoid Windows file locking issues
200+
"%JAVACMD%" "%MAVEN_HOME%\bin\JvmConfigParser.java" "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" "%MAVEN_PROJECTBASEDIR%" "%JVM_CONFIG_TEMP%"
201201
set JVM_CONFIG_EXIT=%ERRORLEVEL%
202202

203203
if defined MAVEN_DEBUG_SCRIPT (
@@ -210,8 +210,6 @@ if %JVM_CONFIG_EXIT% neq 0 (
210210
echo jvm.config path: %MAVEN_PROJECTBASEDIR%\.mvn\jvm.config 1>&2
211211
echo Java command: %JAVACMD% 1>&2
212212
if exist "%JVM_CONFIG_TEMP%" (
213-
echo Parser output: 1>&2
214-
type "%JVM_CONFIG_TEMP%" 1>&2
215213
del "%JVM_CONFIG_TEMP%" 2>nul
216214
)
217215
exit /b 1
@@ -272,6 +270,11 @@ for %%i in ("%MAVEN_HOME%"\boot\plexus-classworlds-*) do set LAUNCHER_JAR="%%i"
272270
set LAUNCHER_CLASS=org.codehaus.plexus.classworlds.launcher.Launcher
273271
if "%MAVEN_MAIN_CLASS%"=="" @set MAVEN_MAIN_CLASS=org.apache.maven.cling.MavenCling
274272

273+
if defined MAVEN_DEBUG_SCRIPT (
274+
echo [DEBUG] Launching JVM with command:
275+
echo [DEBUG] "%JAVACMD%" %INTERNAL_MAVEN_OPTS% %MAVEN_OPTS% %JVM_CONFIG_MAVEN_OPTS% %MAVEN_DEBUG_OPTS% --enable-native-access=ALL-UNNAMED -classpath %LAUNCHER_JAR% "-Dclassworlds.conf=%CLASSWORLDS_CONF%" "-Dmaven.home=%MAVEN_HOME%" "-Dmaven.mainClass=%MAVEN_MAIN_CLASS%" "-Dlibrary.jline.path=%MAVEN_HOME%\lib\jline-native" "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %LAUNCHER_CLASS% %MAVEN_ARGS% %*
276+
)
277+
275278
"%JAVACMD%" ^
276279
%INTERNAL_MAVEN_OPTS% ^
277280
%MAVEN_OPTS% ^

its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh10937QuotedPipesInMavenOptsTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ void testIt() throws Exception {
4242

4343
Verifier verifier = newVerifier(basedir.toString());
4444
verifier.setEnvironmentVariable("MAVEN_OPTS", "-Dprop.maven-opts=\"foo|bar\"");
45+
// Enable debug logging for launcher script to diagnose jvm.config parsing issues
46+
verifier.setEnvironmentVariable("MAVEN_DEBUG_SCRIPT", "1");
4547
verifier.addCliArguments("validate");
4648
verifier.execute();
4749
verifier.verifyErrorFreeLog();

its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh11363PipeSymbolsInJvmConfigTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ void testPipeSymbolsInJvmConfig() throws Exception {
4242

4343
Verifier verifier = newVerifier(basedir.toString());
4444
verifier.setForkJvm(true); // Use forked JVM to test .mvn/jvm.config processing
45+
// Enable debug logging for launcher script to diagnose jvm.config parsing issues
46+
verifier.setEnvironmentVariable("MAVEN_DEBUG_SCRIPT", "1");
4547
verifier.addCliArguments("validate");
4648
verifier.execute();
4749
verifier.verifyErrorFreeLog();

its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh11485AtSignInJvmConfigTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public void testAtSignInJvmConfig() throws Exception {
4040
verifier.addCliArgument(
4141
"-Dexpression.outputFile=" + new File(testDir, "target/pom.properties").getAbsolutePath());
4242
verifier.setForkJvm(true); // custom .mvn/jvm.config
43+
// Enable debug logging for launcher script to diagnose jvm.config parsing issues
44+
verifier.setEnvironmentVariable("MAVEN_DEBUG_SCRIPT", "1");
4345
verifier.addCliArgument("validate");
4446
verifier.execute();
4547
verifier.verifyErrorFreeLog();

its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng4559SpacesInJvmOptsTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ void testIt() throws Exception {
4242

4343
Verifier verifier = newVerifier(basedir.toString());
4444
verifier.setEnvironmentVariable("MAVEN_OPTS", "-Dprop.maven-opts=\"foo bar\"");
45+
// Enable debug logging for launcher script to diagnose jvm.config parsing issues
46+
verifier.setEnvironmentVariable("MAVEN_DEBUG_SCRIPT", "1");
4547
verifier.addCliArguments("validate");
4648
verifier.execute();
4749
verifier.verifyErrorFreeLog();

0 commit comments

Comments
 (0)