Duplicated Java runtime options : what is the order of preference?
Asked Answered
C

7

101

Considering the following command line

java -Xms128m -Xms256m myapp.jar

Which settings will apply for JVM Minimum memory (Xms option) : 128m or 256m ?

Ctenophore answered 29/4, 2010 at 20:56 Comment(1)
No typo in question. Xms options is used twice on purpose. This is the substance of the questionCtenophore
H
32

Depends on the JVM, perhaps the version...perhaps even how many paper clips you have on your desk at the time. It might not even work. Don't do that.

If it's out of your control for some reason, compile and run this the same way you'd run your jar. But be warned, relying on the order of the options is a really bad idea.

public class TotalMemory
{
    public static void main(String[] args)
    {
         System.out.println("Total Memory: "+Runtime.getRuntime().totalMemory());
         System.out.println("Free Memory: "+Runtime.getRuntime().freeMemory());
    }
}
Heartburn answered 29/4, 2010 at 21:17 Comment(2)
+1 - better count those paperclips :-). Seriously, it is not rocket science to change whatever is passing those ambiguous arguments.Jepson
been trying with different number of paper clips. can't find switch to the first oneSorrow
C
74

As always, check your local JVM's specific implementation but here is a quick way to check from the command line without having to code.

> java -version; java -Xmx1G -XX:+PrintFlagsFinal -Xmx2G 2>/dev/null | grep MaxHeapSize

java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
uintx MaxHeapSize         := 2147483648        {product}

So you'll see in this case, the second instance of the argument (2G) is what takes precedence (at least in 1.8) and that has been my experience with most other modern versions as well.

Coppersmith answered 4/11, 2014 at 3:39 Comment(1)
java -Xmx1G -XX:+PrintFlagsFinal -Xmx2G 2>/dev/null | grep MaxHeapSize, this way it's easier to deduce.Paviour
M
43

The IBM JVM treats the rightmost instance of an argument as the winner. I can't speak to HotSpot, etc..

We do this as there are often deeply nested command lines from batch files where people can only add to the end, and want to make that the winner.

Mangosteen answered 30/4, 2010 at 0:48 Comment(2)
+1 for actually answering the question instead of pontificating.Selie
Indeed: ibm.com/support/knowledgecenter/SSYKE2_7.0.0/…Kano
I
40

FTR, OpenJDK 1.7 also seems to take the rightmost value, at least for -Xms.

Inenarrable answered 3/1, 2014 at 11:10 Comment(2)
+1 for actually answering the question instead of pontificating.Selie
just like CSS, the later winsPaviour
H
32

Depends on the JVM, perhaps the version...perhaps even how many paper clips you have on your desk at the time. It might not even work. Don't do that.

If it's out of your control for some reason, compile and run this the same way you'd run your jar. But be warned, relying on the order of the options is a really bad idea.

public class TotalMemory
{
    public static void main(String[] args)
    {
         System.out.println("Total Memory: "+Runtime.getRuntime().totalMemory());
         System.out.println("Free Memory: "+Runtime.getRuntime().freeMemory());
    }
}
Heartburn answered 29/4, 2010 at 21:17 Comment(2)
+1 - better count those paperclips :-). Seriously, it is not rocket science to change whatever is passing those ambiguous arguments.Jepson
been trying with different number of paper clips. can't find switch to the first oneSorrow
P
18

Which settings will apply for JVM Minimum memory?

In the various versions of Java listed below, the "winner" is the right-most value in the argument list. As others have pointed out, it is not a good idea to rely on this, but perhaps this is useful information to share nonetheless.

Java 1.8.0_172

~ $ java8
java version "1.8.0_172"
Java(TM) SE Runtime Environment (build 1.8.0_172-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.172-b11, mixed mode)
~ $ java -Xmx1024m -Xmx4024m -XX:+PrintFlagsFinal Test 2>/dev/null | grep MaxHeapSize
    uintx MaxHeapSize                              := 4219469824                          {product}

Java 11.0.3

~ $ java11
java version "11.0.3" 2019-04-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.3+12-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.3+12-LTS, mixed mode)
~ $ java -Xmx1024m -Xmx4024m -XX:+PrintFlagsFinal Test 2>/dev/null | grep MaxHeapSize
   size_t MaxHeapSize                              = 4219469824                                {product} {command line}

OpenJDK 12.0.1

~ $ java12
openjdk version "12.0.1" 2019-04-16
OpenJDK Runtime Environment (build 12.0.1+12)
OpenJDK 64-Bit Server VM (build 12.0.1+12, mixed mode, sharing)
~ $ java -Xmx1024m -Xmx4024m -XX:+PrintFlagsFinal Test 2>/dev/null | grep MaxHeapSize
   size_t MaxHeapSize                              = 4219469824                                {product} {command line}

AdoptOpenJDK 12.0.1

~ $ java12a
openjdk version "12.0.1" 2019-04-16
OpenJDK Runtime Environment AdoptOpenJDK (build 12.0.1+12)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 12.0.1+12, mixed mode, sharing)
~ $ java -Xmx1024m -Xmx4024m -XX:+PrintFlagsFinal Test 2>/dev/null | grep MaxHeapSize
   size_t MaxHeapSize                              = 4219469824                                {product} {command line}

OpenJDK 13-ea

~ $ java13
openjdk version "13-ea" 2019-09-17
OpenJDK Runtime Environment (build 13-ea+22)
OpenJDK 64-Bit Server VM (build 13-ea+22, mixed mode, sharing)
~ $ java -Xmx1024m -Xmx4024m -XX:+PrintFlagsFinal Test 2>/dev/null | grep MaxHeapSize
   size_t MaxHeapSize                              = 4219469824                                {product} {command line}
Pucker answered 14/10, 2019 at 22:20 Comment(1)
this behavior remains consistent in Java SE 11.0.14 (build 11.0.14+8-LTS-263), as well as OpenJDK 17.0.1 (build 17.0.1+12-39)Pucker
S
10

I bet it's the second one. Arguments are usually processed in the order:

for( int i=0; i<argc; i++ ) {
  process_argument(argv[i]);
}

But if I were writing java argument parser, I'd complain on conflicting arguments.

Sawyer answered 29/4, 2010 at 21:30 Comment(0)
I
0

My experiments show that it takes the maximum value of xmx.

So if you pass in -xmx4g -xmx1g it will take 4t, and if you pass in -xmx1g -xmx4g it will still take 4g.

Ineptitude answered 10/6, 2021 at 11:51 Comment(2)
This isn't the behaviour I see in AdoptOpenJDK-11.0.11+9, using java -version; java -Xmx2G -Xmx1G -XX:+PrintFlagsFinal 2>/dev/null | grep MaxHeapSizeHenricks
I would encourage more, and different, experimentation. my own experiments (detailed in another answer on this same question) show that the max value is not used in Java SE versions 1.8.0, 11.0.3, 11.0.14 as well OpenJDK versions 12.0.1, 13, and 17.0.1. instead, the right-most value is used.Pucker

© 2022 - 2024 — McMap. All rights reserved.