Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
Windows: cannot pass java opts that contain whitespaces #4858
Disclaimer: that's NOT yet another "scala won't work if SCALA_HOME resides in C:\Program Files (x86)" issue. Please, take a look at the details provided below.
Here's the excerpt from scala.bat that contains the bug (though, the bug affects not only scala.bat, but all batch files that work with JAVA_OPTS):
rem We use the value of the JAVA_OPTS environment variable if defined
Since the expansion of _JAVA_OPTS is wrapped in quotes, it works finely when the variable contains spaces (i.e. if the user has provided more than one javaopt). However, it fails when the variable itself contains quotes. As explained in http://stackoverflow.com/questions/430376/batch-files-vista-x64-if-and-parenthesis, in batch files, variables in "if" statements are expanded before the "if" statement is parsed. That's why, after the variable expansion, the "if" line no longer conforms to the "if == " pattern (since we get multiple strings instead of the first ), and command interpreter reports an error.
This issue could be dismissed as insignificant, but it blocks an important use-case, namely passing a string with spaces as a javaopt value. The exceprt provided below explains that:
"%_JAVACMD%" %_JAVA_OPTS% %_PROPS% -cp "%_TOOL_CLASSPATH%" scala.tools.nsc.MainGenericRunner %*
That's the raison d'etre of the script. Note, that the variable expansion of _JAVA_OPTS here is not guarded by quotes. This means that the user herself has to protect whitespaces in her javaopts. The only way to do that is to use quotes, e.g. like that:
SET JAVA_OPTS="-Dfoo=qu ux" "-Dbar=bar"
But in that case, scala.bat will fail when the batch interpreter reaches the "if" line due to the reasons outlined above.
A fix that won't work
This bug cannot be fixed by simply quoting %JAVA_OPTS% or %_JAVA_OPTS% expansions in the script. If we quote the expansion in "set _JAVA_OPTS=%JAVA_OPTS%", then _JAVA_OPTS itself will contain quotes (since set does not remove quotes automatically). If we quote the expansion in "%_JAVACMD% %_JAVA_OPTS% ...", then we got two problems: 1) if _JAVA_OPTS does not contain quotes, it will be passed as a single command-line parameter, even if it contains multiple javaopts, 2) if _JAVA_OPTS contains quotes, the interpreter will get confused and will incorrectly chop it into command-line arguments to JAVACMD.
A fix that will work
Luckily, there's a very simple fix to the problem. We only have to replace the check at the "if" line with "if not defined _JAVA_OPTS". That check does not perform variable expansion at all, that's why we completely evade quoting issues.
if "%_JAVA_OPTS%"=="" set _JAVA_OPTS=-Xmx256M -Xms32M
if not defined _JAVA_OPTS set _JAVA_OPTS=-Xmx256M -Xms32M
Scala batch scripts also contain other checks that might suffer from the same idiosyncrasy of Windows batch interpreter. For example, if "%_JAVACMD%" == "" or if not "%JAVA_HOME%"=="". However, the analysis of whether this will lead to issues has yet to be done.
Imported From: https://issues.scala-lang.org/browse/SI-4858?orig=1