0

I can't for the life of me figure out why -Xmx in MAVEN_OPTS doesn't work for Maven in openjdk:8-jdk-alpine.

This:

$ docker run --rm openjdk:8-jdk-alpine sh -c 'apk add maven && MAVEN_OPTS=-Xmx2g\ -Xms2g mvn --version'

Produces:

Error occurred during initialization of VM
Initial heap size set to a larger value than the maximum heap size

I've used -XX:+PrintFlagsFinal to look at MaxHeapSize with various settings and here's what I found:

  • Apparently -Xmx is fixed to 512mb regardless of what's specified. Other options such as -Xms and -XX:+PrintFlagsFinal work as expected:

    $ docker run --rm openjdk:8-jdk-alpine sh -c 'apk add maven && \
        MAVEN_OPTS="-Xmx123m -Xms123m -XX:+PrintFlagsFinal" mvn --version | egrep "(Initial|Max)HeapSize"'
    
        uintx InitialHeapSize                          := 130023424                           {product}
        uintx MaxHeapSize                              := 536870912                           {product}
    
  • apt add maven is installing maven version 3.6.0-r0 but trying with other versions also produce the same result. For example, 3.6.1-r0 in Alpine 3.10 and 3.5.2-r0 in Alpine 3.7 produced the same result:

    $ docker run openjdk:8-jdk-alpine sh -c 'sed -e s:/v3.9/:/v3.10/: /etc/apk/repositories -i && \
        apk add maven && MAVEN_OPTS=-Xmx2g\ -XX:+PrintFlagsFinal mvn -version | fgrep MaxHeapSize'
    
  • I've looked for ~/.m2/settings.xml and ./.mvn as mentioned in https://maven.apache.org/configure.html but neither seem to exist:

    $ docker run --rm openjdk:8-jdk-alpine sh -c 'apk add maven && ls ~/.m2'
    
  • java seems to support -Xmx fine:

    $ docker run --rm openjdk:8-jdk-alpine sh -c 'java -Xmx2g -XX:+PrintFlagsFinal -version | fgrep MaxHeapSize'
    
  • The problem doesn't occur if maven:3.6.0-jdk-8-alpine is used instead of openjdk:8-jdk-alpine:

    $ docker run --rm maven:3.6.0-jdk-8-alpine sh -c \
        'MAVEN_OPTS=-Xmx2g\ -XX:+PrintFlagsFinal mvn --version | fgrep MaxHeapSize'
    
  • Using _JAVA_OPTIONS instead of MAVEN_OPTS works as a workaround:

    $ docker run --rm openjdk:8-jdk-alpine sh -c 'apk add maven && \
        _JAVA_OPTIONS=-Xmx2g\ -XX:+PrintFlagsFinal mvn --version | fgrep MaxHeapSize'
    

Question is, how is -Xmx in MAVEN_OPTS being ignored for Maven in openjdk:8-jdk-alpine?

antak
  • 15,500
  • 7
  • 59
  • 72
  • `MAVEN_OPTS` is an environment variable for Maven and NOT for the JDK which you are using via `docker run --rm openjdk:8-jdk-alpine..` If you are using the image `docker run --rm maven:3.6.0-jdk-8-alpine` which is a Maven image where you can simply define via `-e MAVEN_OPTS="..."` (as environment variable)... where no need is to use `sh -c 'MAVEN_OPTS=-Xmx2g\ -XX:+PrintFlagsFinal mvn --version..` .... – khmarbaise Apr 27 '21 at 15:38
  • `MAVEN_OPTS` a [standard way](https://stackoverflow.com/questions/12498738) of setting JVM options such as `-Xmx` [even on offical documentation](https://maven.apache.org/configure.html). I could set it through `docker run`'s `-e` like you said or through the `VAR=value cmd` syntax of the shell but it doesn't really make a difference to `mvn` does it? This seems moot as far as the issue is concerned but if I'm going to have a shell anyway to do `apk add maven` then why not put it in front of the command as it's shorter that way. – antak Apr 28 '21 at 01:40
  • You seemed to misunderstand my point: MAVEN_OPTS is not a standard way setting JVM options in general it's way to set JVM options for the JVM which is used by Maven (technically it's used by `mvn` script to [configure the JVM options](https://github.com/apache/maven/blob/maven-3.8.1/apache-maven/src/bin/mvn)). The usage via `docker run -e MAVEN_OPTS..` will only work for the Maven image(`maven:3.6.0-jdk-8-alpine`) but not for the `openjdk:8-jdk-alpine` image and of course the behaviour changes if you use different images. – khmarbaise Apr 28 '21 at 08:35
  • I thought the comment was pointing out something problematic with some code in the question but I couldn't tell which part. The `docker run -e MAVEN_OPTS=...` syntax first appeared in your comment and all code in the question uses the `MAVEN_OPTS=... mvn` syntax where `MAVEN_OPTS` goes directly into the `mvn` script. – antak Apr 29 '21 at 00:39

1 Answers1

1

This obscure problem is documented in this equally hard to find bug report. Basically, Maven on Alpine Linux is packaged with an /etc/mavenrc file containing these lines:

M2_HOME="$m2_home"
MAVEN_OPTS="\$MAVEN_OPTS -Xmx512m"

The problem lies in the second line which hard codes -Xmx to 512m. So yes, -Xmx cannot be set through MAVEN_OPTS on Alpine Linux's vanilla Maven as of time of writing.

To test, simply remove the file and try again:

$ docker run --rm openjdk:8-jdk-alpine sh -c 'apk add maven && rm /etc/mavenrc && \
    MAVEN_OPTS=-Xmx2g\ -XX:+PrintFlagsFinal mvn --version | fgrep MaxHeapSize'

MaxHeapSize should then be set to the desired 2g.

The bug report is three years old and probably hasn't gained more traction because there's couple of conditions that need satisfying: Using Maven on Alpine Linux and requiring more than 512m to build.

A person who stumbles on this has few options:

  • Use _JAVA_OPTIONS instead of MAVEN_OPTS for setting -Xmx
  • Remove the second line of /etc/mavenrc

Hopefully for them, an OOM error will come quickly and painlessly, instead of extremely slow builds due to excessive GC'ing.

antak
  • 15,500
  • 7
  • 59
  • 72