sbt-native-packager icon indicating copy to clipboard operation
sbt-native-packager copied to clipboard

"Improperly specified VM option" on Windows

Open mrubin opened this issue 4 years ago • 10 comments

Using sbt 1.4.4 to create a zip for a Play Framework (2.8) project via sbt dist.

I am specifying javaOptions just like seen in the documentation. These are my exact settings:

  javaOptions in Universal ++= Seq(
    "-J-server",
    "-Djava.awt.headless=true",
    "-Dpidfile.path=/dev/null",
    "-J-Xms576M",
    "-J-Xmx576M",
    "-J-XX:+AlwaysPreTouch",
    "-J-XX:+UseStringDeduplication",
    /* Begin G1GC Section */
    "-J-XX:+UseG1GC",
    "-J-XX:+UnlockExperimentalVMOptions",
    "-J-XX:MaxGCPauseMillis=500",             
    "-J-XX:G1NewSizePercent=30",              
    "-J-XX:G1MaxNewSizePercent=80",           
    "-J-XX:+ParallelRefProcEnabled",          
    "-J-XX:InitiatingHeapOccupancyPercent=35" 
    /* End G1GC Section */
  )

This creates an application.ini file as follows:

# options from build
-J-server
-Djava.awt.headless=true
-Dpidfile.path=/dev/null
-J-Xms576M
-J-Xmx576M
-J-XX:+AlwaysPreTouch
-J-XX:+UseStringDeduplication
-J-XX:+UseG1GC
-J-XX:+UnlockExperimentalVMOptions
-J-XX:MaxGCPauseMillis=500
-J-XX:G1NewSizePercent=30
-J-XX:G1MaxNewSizePercent=80
-J-XX:+ParallelRefProcEnabled
-J-XX:InitiatingHeapOccupancyPercent=35

This works fine on Mac and Linux, but results in "Improperly specified VM option 'MaxGCPauseMillis'" on Windows (with Java 8), when executing the .bat file in the bin folder.

Either of the following changes work for Windows, but do not work on Mac/Linux:

# options from build
-J-server
-Djava.awt.headless=true
-Dpidfile.path=/dev/null
-J-Xms576M
-J-Xmx576M
-J-XX:+AlwaysPreTouch
-J-XX:+UseStringDeduplication
-J-XX:+UseG1GC
-J-XX:+UnlockExperimentalVMOptions
"-J-XX:MaxGCPauseMillis=500"
"-J-XX:G1NewSizePercent=30"
"-J-XX:G1MaxNewSizePercent=80"
-J-XX:+ParallelRefProcEnabled
"-J-XX:InitiatingHeapOccupancyPercent=35"
# options from build
-J-server
-Djava.awt.headless=true
-Dpidfile.path=/dev/null
-J-Xms576M
-J-Xmx576M
-J-XX:+AlwaysPreTouch
-J-XX:+UseStringDeduplication
-J-XX:+UseG1GC
-J-XX:+UnlockExperimentalVMOptions
-J-XX:MaxGCPauseMillis=<500>
-J-XX:G1NewSizePercent=<30>
-J-XX:G1MaxNewSizePercent=<80>
-J-XX:+ParallelRefProcEnabled
-J-XX:InitiatingHeapOccupancyPercent=<35>

How do I set my javaOptions in a way that works on both Mac/Linux and Windows?

mrubin avatar Jan 09 '21 02:01 mrubin

Seems like the default .bat file has a bug. It's removing the equal sign and whatever is on the right of it, from the entries. I re-ran the Windows .bat file and printed !_JAVA_OPTS!.

The following application.ini entries:

-J-server
-Djava.awt.headless=true
-Dpidfile.path=/dev/null
-J-Xms576M
-J-Xmx576M
-J-XX:+AlwaysPreTouch
-J-XX:+UseStringDeduplication
-J-XX:+UseG1GC
-J-XX:+UnlockExperimentalVMOptions
-J-XX:MaxGCPauseMillis=500
-J-XX:G1NewSizePercent=30
-J-XX:G1MaxNewSizePercent=80
-J-XX:+ParallelRefProcEnabled
-J-XX:InitiatingHeapOccupancyPercent=35

get transformed into the following !_JAVA_OPTS!:

  -server -Djava.awt.headless=true -Dpidfile.path=/dev/null -Xms576M -Xmx576M -XX:+AlwaysPreTouch -XX:+UseStringDeduplication -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:MaxGCPauseMillis -XX:G1NewSizePercent -XX:G1MaxNewSizePercent -XX:+ParallelRefProcEnabled -XX:InitiatingHeapOccupancyPercent

mrubin avatar Jan 09 '21 04:01 mrubin

Hi @mrubin Thanks for the detailed error report.

Let me recap that I get this straight. Quoted works on windows, but not on Unix systems? E.g.

"-J-XX:MaxGCPauseMillis=500"

I must admit the application.ini was something I implemented years ago and wasn't the greatest idea IMHO. Having that said, as described in the docs you linked it should be possible to provide two different application.ini files.

  • remove javaOptions in Universal
  • create src/universal/conf/application.bat.ini and src/universal/conf/application.bash.ini
  • configure bash and bat config locations
bashScriptConfigLocation := Some("${app_home}/../conf/application.bash.ini")
batScriptConfigLocation := Some("%APP_HOME%\\conf\\application.bat.ini")

muuki88 avatar Jan 11 '21 16:01 muuki88

Hi @muuki88 - thank you for the quick response. You're correct,

"-J-XX:MaxGCPauseMillis=500"

works on Windows, but not Unix systems. I tried various tweaks and the error I get on Mac/Linux is along the lines of:

Bad root server path: /Users/.../my-project/"-J-server"

I found your suggested solution as well and it should work, but I was considering it a workaround. I don't think it's ideal long-term for the settings to be split between 2 locations - that makes it possible that they would go out of sync in the future.

It seems like the .bat file stripping the = sign is a bug - do you agree? If so, is there anyone knowledgeable with .bat files that could take a stab at a fix? It seems like that would be the proper long-term solution.

mrubin avatar Jan 11 '21 16:01 mrubin

It seems like the .bat file stripping the = sign is a bug - do you agree?

Absolutely :+1:

If so, is there anyone knowledgeable with .bat files that could take a stab at a fix? It seems like that would be the proper long-term solution.

That's the issue :smile: Windows users are rare. Combined with sbt knowledge and time to contribute even rarer. I guess the logic is in this :parseConfig method, but I have really no idea how this works.

I found your suggested solution as well and it should work, but I was considering it a workaround. I don't think it's ideal long-term for the settings to be split between 2 locations - that makes it possible that they would go out of sync in the future.

I agree with you. What I tried to say with my previous comment "the application.ini wasn't the greatest idea" is that I would not recommend using it today. The bashScriptExtraDefines and batScriptExtraDefines are more robust and less magic as these things will just be added to the resulting scripts.

However the solution would be the same. Duplicate the configuration options.

So I'm trying to summon @dwickern or @nigredo-tori who were the last two people that were able to properly change something in the bat file :hear_no_evil: :heart_eyes:

muuki88 avatar Jan 11 '21 18:01 muuki88

The issue appears to be in these lines of :process_args

Before calling :process_args, the application.ini entries look correct and after :process_args they are broken.

mrubin avatar Jan 11 '21 20:01 mrubin

https://stackoverflow.com/questions/20572424/preserving-equal-characters-in-batch-file-parameters may be relevant.

It looks like entries with = which are not surrounded by " (which does not work on Unix systems) treat the left-hand-side and right-hand-side of the equals as separate params:

-J-XX:MaxGCPauseMillis
500
-J-XX:G1NewSizePercent
30
...

And the numbers are then stripped by the ignore arguments that do not start with '-' check.

mrubin avatar Jan 11 '21 20:01 mrubin

Thanks for the research and links. This part in the :process_args looks rather suspicious:

https://github.com/sbt/sbt-native-packager/blob/fd2c1e3f6dde2c851cd5da91b3b77ab99c4e84cd/src/main/resources/com/typesafe/sbt/packager/archetypes/scripts/bat-template#L159-L169

Maybe this is the line were we could add the additional quoting?

muuki88 avatar Jan 12 '21 12:01 muuki88

I'm not sure that those lines are even hit in my scenario (where the entries in application.ini are not surrounded by double-quotes).

What I'm seeing for my scenario is that as the arguments are processed one at a time (and then shift is used to go to the next one), the left-hand-side and right-hand-side of the equals are split into separate arguments:

-J-XX:MaxGCPauseMillis
500
-J-XX:G1NewSizePercent
30
...

The entries that begin with -J are properly processed and are in the final output, and the entries that are just the numbers are also properly processed in that they don't look like a java command-line option and are stripped.

I think the issue is with the approach that :process_args is using to iterate through the arguments - the arguments which contain an = get split into two by this approach and would need to be "put back together" somehow. Or, a different approach needs to be used to iterate through the arguments - one that does not result in splitting them at the =.

mrubin avatar Jan 12 '21 17:01 mrubin

@muuki88 Any updates on this?

mrubinwch avatar Mar 31 '21 23:03 mrubinwch

Nope 😔 some one from the community with windows experience would need to step up and fix this.

muuki88 avatar Apr 01 '21 05:04 muuki88