Short answer: All memory sizes used by the JVM command line arguments are specified in the traditional binary units, where a kilobyte is 1024 bytes, and the others are increasing powers of 1024.

Long answer:

This documentation page on the command line arguments says the following applies to all the arguments accepting memory sizes:

For example, to set the size to 8 GB, you can specify either 8g, 8192m, 8388608k, or 8589934592 as the argument.

For -Xmx, it gives these specific examples:

The following examples show how to set the maximum allowed size of allocated memory to 80 MB using various units:

-Xmx83886080
-Xmx81920k
-Xmx80m

Before I thought to check the documentation (I assumed you already had?), I checked the source of HotSpot and found the memory values are parsed in src/share/vm/runtime/arguments.cpp by the function atomull (which seems to stand for "ASCII to memory, unsigned long long"):

// Parses a memory size specification string.
static bool atomull(const char *s, julong* result) {
  julong n = 0;
  int args_read = sscanf(s, JULONG_FORMAT, &n);
  if (args_read != 1) {
    return false;
  }
  while (*s != '\0' && isdigit(*s)) {
    s++;
  }
  // 4705540: illegal if more characters are found after the first non-digit
  if (strlen(s) > 1) {
    return false;
  }
  switch (*s) {
    case 'T': case 't':
      *result = n * G * K;
      // Check for overflow.
      if (*result/((julong)G * K) != n) return false;
      return true;
    case 'G': case 'g':
      *result = n * G;
      if (*result/G != n) return false;
      return true;
    case 'M': case 'm':
      *result = n * M;
      if (*result/M != n) return false;
      return true;
    case 'K': case 'k':
      *result = n * K;
      if (*result/K != n) return false;
      return true;
    case '\0':
      *result = n;
      return true;
    default:
      return false;
  }
}

Those constants K, M, G are defined in src/share/vm/utilities/globalDefinitions.hpp:

const size_t K                  = 1024;
const size_t M                  = K*K;
const size_t G                  = M*K;

All this confirms the documentation, except that support for the T suffix for terabytes was apparently added later and is not documented at all.

It is not mandatory to use a unit multiplier, so if you want one billion bytes you can write -Xmx1000000000. If you do use a multiplier, they're binary, so -Xmx1G means 230 bytes, or one stick o' RAM.

(Which is not really surprising, because Java predates the IEC's attempt to retroactively redefine existing words. Confusion could have been saved if the IEC had merely advised disambiguating the memory units with the qualifiers "binary" and "decimal" the occasional times their meaning wasn't clear. E.g., binary gigabytes (GB2) = 10243 bytes, and decimal gigabytes (GB10) = 10003 bytes. But no, they redefined the words everyone was already using, inevitably exploding confusion, and leaving us stuck with these clown terms "gibibyte", "tebibyte" and the rest. Oh God spare us.)

Answer from Boann on Stack Overflow
Top answer
1 of 3
78

Short answer: All memory sizes used by the JVM command line arguments are specified in the traditional binary units, where a kilobyte is 1024 bytes, and the others are increasing powers of 1024.

Long answer:

This documentation page on the command line arguments says the following applies to all the arguments accepting memory sizes:

For example, to set the size to 8 GB, you can specify either 8g, 8192m, 8388608k, or 8589934592 as the argument.

For -Xmx, it gives these specific examples:

The following examples show how to set the maximum allowed size of allocated memory to 80 MB using various units:

-Xmx83886080
-Xmx81920k
-Xmx80m

Before I thought to check the documentation (I assumed you already had?), I checked the source of HotSpot and found the memory values are parsed in src/share/vm/runtime/arguments.cpp by the function atomull (which seems to stand for "ASCII to memory, unsigned long long"):

// Parses a memory size specification string.
static bool atomull(const char *s, julong* result) {
  julong n = 0;
  int args_read = sscanf(s, JULONG_FORMAT, &n);
  if (args_read != 1) {
    return false;
  }
  while (*s != '\0' && isdigit(*s)) {
    s++;
  }
  // 4705540: illegal if more characters are found after the first non-digit
  if (strlen(s) > 1) {
    return false;
  }
  switch (*s) {
    case 'T': case 't':
      *result = n * G * K;
      // Check for overflow.
      if (*result/((julong)G * K) != n) return false;
      return true;
    case 'G': case 'g':
      *result = n * G;
      if (*result/G != n) return false;
      return true;
    case 'M': case 'm':
      *result = n * M;
      if (*result/M != n) return false;
      return true;
    case 'K': case 'k':
      *result = n * K;
      if (*result/K != n) return false;
      return true;
    case '\0':
      *result = n;
      return true;
    default:
      return false;
  }
}

Those constants K, M, G are defined in src/share/vm/utilities/globalDefinitions.hpp:

const size_t K                  = 1024;
const size_t M                  = K*K;
const size_t G                  = M*K;

All this confirms the documentation, except that support for the T suffix for terabytes was apparently added later and is not documented at all.

It is not mandatory to use a unit multiplier, so if you want one billion bytes you can write -Xmx1000000000. If you do use a multiplier, they're binary, so -Xmx1G means 230 bytes, or one stick o' RAM.

(Which is not really surprising, because Java predates the IEC's attempt to retroactively redefine existing words. Confusion could have been saved if the IEC had merely advised disambiguating the memory units with the qualifiers "binary" and "decimal" the occasional times their meaning wasn't clear. E.g., binary gigabytes (GB2) = 10243 bytes, and decimal gigabytes (GB10) = 10003 bytes. But no, they redefined the words everyone was already using, inevitably exploding confusion, and leaving us stuck with these clown terms "gibibyte", "tebibyte" and the rest. Oh God spare us.)

2 of 3
7

You have two options to get answer for your question:

a) inspect source code of JDK. Sorry I was unable to google it in 5 minutes.

b) write a simulation, run it several times and make some observations.

public class A {
  public static void main(String[] args) throws Exception {
    System.out.println("total: " + Runtime.getRuntime().totalMemory());
  }
}

And run it several times:

java -Xms130m -Xmx2G A
total: 131072000
java -Xms131m -Xmx2G A
total: 132644864
java -Xms132m -Xmx2G A
total: 132644864
java -Xms133m -Xmx2G A
total: 134742016
java -Xms134m -Xmx2G A
total: 134742016

So educated guess is that java uses not an exact number, but 2^n approximation of the number you requested.

🌐
Sentry
sentry.io › sentry answers › java › understanding the java virtual machine's -xms and -xmx parameters
Understanding the Java Virtual Machine's -Xms and -Xmx parameters | Sentry
April 15, 2024 - When both of these example parameter values are used together, i.e. -Xms256m -Xmx1g, the size of the heap will initially be 256 megabytes but will be allowed to grow to 1 gigabyte during the program’s lifecycle.
🌐
Upsun
support.platform.sh › hc › en-us › community › posts › 16439663935378-Java-Memory-commands
Java Memory commands - Platform.sh - Upsun
March 5, 2020 - This value must be a multiple of 1024 and greater than 2 MB. Append the letter k or K to indicate kilobytes, m or M to indicate megabytes, and g or G to indicate gigabytes. The default value is chosen at runtime based on system configuration.
🌐
ycrash Answers
answers.ycrash.io › question › what-is-maximum-heap-size--xmx-
What is Maximum Heap Size: -Xmx? - yCrash Answers
-XmxNNN where NNN is a number indicating the amount of memory, including an optional character indicating the unit. For example -Xmx8g indicates a maximum heap size of 8 gigabytes.
🌐
Reddit
reddit.com › r/admincraft › best values for min-max ram, xms & xmx arguments
r/admincraft on Reddit: Best values for min-max RAM, Xms & Xmx arguments
September 20, 2019 -

Edit: Solved, just set them both to the same value!

---

So when running my server (which has 8GB or RAM) I set my Xms to 2G (minimum RAM) and Xmx to 6GB (maximum RAM). From what I understand this means the server will always use 2GB of RAM but can take up to 6GB if it needs it. It's running on a dedicated Ubuntu server that does nothing but run the MC server, so 2GB for the OS etc. should be fine.

However, I've also read that giving MC too much RAM is bad, and garbage collection will go haywire. I managed to find some good but very cheap RAM so I'll be upgrading to 16GB of RAM this weekend.

My question is, how to determine what to set the min RAM to and what the max RAM? I just picked 2GB as the minimum value at random, as it seemed like a good amount to give the server at minimum. When I put the 16GB in I want to allocate 12GB to my MC server, should I keep the min at 2GB and set the max to 12GB? Could this lead to issues?

My launch parameters (added some line breaks for readability):

java -server -Xms2G -Xmx6G -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:MaxGCPauseMillis=100 
-XX:+DisableExplicitGC -XX:TargetSurvivorRatio=90 -XX:G1NewSizePercent=50 -XX:G1MaxNewSizePercent=80 
-XX:G1MixedGCLiveThresholdPercent=35 -XX:+AlwaysPreTouch -XX:+ParallelRefProcEnabled 
-Dusing.aikars.flags=mcflags.emc.gs 
-jar $(ls -v | grep -i "FTBServer.*jar\|forge.*jar\|paper-*.*jar\|spigot-*.*jar\|minecraft_server.*jar" | head -n 1) nogui
🌐
Educative
educative.io › answers › xms-and-xmx-java
xmx and xms Java
// FORMAT: java -xms{Numerical Size}{Unit} java -xms1G · java -xms512m · // Omitting Unit will result in the size being interpreted as byte · java -xms1024 · xmx is used to specify the upper bound of java heap memory size.
Find elsewhere
🌐
Alvin Alexander
alvinalexander.com › blog › post › java › java-xmx-xms-memory-heap-size-control
How to control Java heap size (memory) allocation (xmx, xms) | alvinalexander.com
January 31, 2026 - -Xms64m or -Xms64M // 64 megabytes (initial memory) -Xmx1g or -Xmx1G // 1 gigabyte (maximum memory) A complete java command looks like this: java -Xmx64m -Xmx2G -classpath ".:${THE_CLASSPATH}" ${PROGRAM_NAME} See the rest of this article for more details. Also see my Java heap and stack definitions ...
🌐
IBM
ibm.com › docs › en › sdk-java-technology › 8
-Xms / -Xmx - IBM Documentation
January 22, 2026 - For example, for a VM with 16 GB RAM, the default maximum size is 25% of RAM, therefore the default value of Xmx will be 4 GB. If the initial size is specified as 6 GB (-Xms6g), then -Xms (6 GB) is greater than -Xmx (4 GB) and before the 0.53.0 ...
🌐
Oracle
docs.oracle.com › cd › E13150_01 › jrockit_jvm › jrockit › jrdocs › refman › optionX.html
-X Command-line Options
java -Xmx:1g myApp · sets the maximum java heap to 1 gigabyte. If you do not add a unit, you will get the exact value you state; for example, 64 will be interpreted as 64 bytes, not 64 megabytes or 64 kilobytes. The -Xmx option and -Xms option in combination are used to limit the Java heap size.
🌐
Index.dev
index.dev › blog › check-xmx-value-java-runtime
Java Xmx: Check Max Heap Size at Runtime | -Xmx Command & Examples | Index.dev
February 14, 2025 - bash java -Xmx512m MyApp # 512 megabytes java -Xmx2g MyApp # 2 gigabytes java -Xmx4096m MyApp # 4096 MB (4 GB)
🌐
Eclipse Foundation
eclipse.dev › openj9 › docs › xms
-Xms / -Xmx -
For example, for a VM with 16 GB RAM, the default maximum size is 25% of RAM, therefore the default value of Xmx will be 4 GB. If the initial size is specified as 6 GB (-Xms6g), then -Xms (6 GB) is greater than -Xmx (4 GB) and before the 0.53.0 release that VM used to fail.
🌐
Medium
medium.com › @maheshwar.ramkrushna › understanding-heap-size-and-its-impact-on-java-application-performance-d4c312bbd13c
Understanding Heap Size and its Impact on Java Application Performance | by Ramkrushna Maheshwar | Medium
May 25, 2023 - In this example, the “-Xms” option sets the initial heap size to 256 megabytes (MB), and the “-Xmx” option sets the maximum heap size to 1024 MB (or 1 gigabyte).
🌐
Readthedocs
ovarflow.readthedocs.io › en › latest › ResourceRequirements › Benchmarking › JavaXmx.html
Java Heap Space (-Xmx) — OVarFlow 2.0 documentation
CPU usage is negatively effected by low heap sizes, reaching a sustainable minimum at approx. 12 Gb. Generally memory usage raises with higher values for the Xmx setting, but with a drop at 8 Gb. The gray line in the RSS plot indicates parity between measured RSS and set Xmx values (meaning ...
🌐
Getisymphony
docs.getisymphony.com › bin › view › iSymphony 3.5 Documentation › iSymphony Installation and Update Guide › Installing iSymphony › Advanced Installation Topics › Increasing JVM maximum memory allocation
Increasing JVM maximum memory allocation - XWiki
September 9, 2021 - java -Xmx:1g myApp · sets the maximum java heap to 1 gigabyte. If you do not add a unit, you will get the exact value you state; for example, 64 will be interpreted as 64 bytes, not 64 megabytes or 64 kilobytes. The -Xmx option and -Xms option in combination are used to limit the Java heap size.
🌐
Azul
docs.azul.com › prime › Heap-Size
Recommended Heap Size
The default value is 1.5625% of the total system memory or cgroup/container limit, and ranges from a minimum 128 MB to a maximum 2 GB. When ZST is installed, this parameter is ignored and the minimum heap size is equal to -Xmx, except when heap elasticity is enabled.
🌐
Grokipedia
grokipedia.com › xmx
xmx — Grokipedia
March 28, 2026 - The -Xmx option is a non-standard command-line flag for the Java launcher (java) that specifies the maximum size, in bytes, of the heap—the memory allocation pool available to Java applications running on the Java Virtual Machine (JVM).[1] ...