diff --git a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java index 346661e9247bc..c1bd8b968b084 100644 --- a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java +++ b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java @@ -95,6 +95,8 @@ public class NativeImage { private static final String DEFAULT_GENERATOR_9PLUS_SUFFIX = "$JDK9Plus"; private static final String CUSTOM_SYSTEM_CLASS_LOADER = NativeImageSystemClassLoader.class.getCanonicalName(); + private static final int WINDOWS_MAX_COMMAND_LENGTH = 32768; + static final boolean IS_AOT = Boolean.getBoolean("com.oracle.graalvm.isaot"); static final String platform = getPlatform(); @@ -1175,8 +1177,7 @@ protected static List createImageBuilderArgs(LinkedHashSet image protected int buildImage(List javaArgs, LinkedHashSet bcp, LinkedHashSet cp, LinkedHashSet imageArgs, LinkedHashSet imagecp) { /* Construct ProcessBuilder command from final arguments */ - ProcessBuilder pb = new ProcessBuilder(); - List command = pb.command(); + List command = new ArrayList<>(); command.add(canonicalize(config.getJavaExecutable()).toString()); command.addAll(javaArgs); if (!bcp.isEmpty()) { @@ -1203,11 +1204,30 @@ protected int buildImage(List javaArgs, LinkedHashSet bcp, LinkedH } int exitStatus = 1; + File argsFile = null; try { + if (OS.getCurrent() == OS.WINDOWS) { + int totalLength = command.stream().mapToInt(s -> s.length() + 1).sum(); + if (totalLength >= WINDOWS_MAX_COMMAND_LENGTH) { + argsFile = File.createTempFile("native-image", "args"); + argsFile.deleteOnExit(); + Files.write(argsFile.toPath(), (Iterable) command.stream().skip(1)::iterator); + List atCommand = new ArrayList<>(); + atCommand.add(command.get(0)); + atCommand.add("@" + argsFile); + command = atCommand; + } + } + ProcessBuilder pb = new ProcessBuilder(); + pb.command(command); Process p = pb.inheritIO().start(); exitStatus = p.waitFor(); } catch (IOException | InterruptedException e) { throw showError(e.getMessage()); + } finally { + if (argsFile != null) { + argsFile.delete(); + } } return exitStatus; }