Is -Xmx a hard limit?

This SO answer clarifies a few things about the -Xmx JVM -Xmx . Trying to experiment, I did the following:

 import java.util.List; import java.util.ArrayList; public class FooMain { private static String memoryMsg() { return String.format("%s. %s. %s" , String.format("total memory is: [%d]",Runtime.getRuntime().totalMemory()) , String.format("free memory is: [%d]",Runtime.getRuntime().freeMemory()) , String.format("max memory is: [%d]",Runtime.getRuntime().maxMemory())); } public static void main(String args[]) { String msg = null; try { System.out.println(memoryMsg()); List<Object> xs = new ArrayList<>(); int i = 0 ; while (true) { xs.add(new byte[1000]); msg = String.format("%d 1k arrays added.\n%s.\n" , ++i , memoryMsg()); } } finally { System.out.printf(msg); } } } 

Compile it with javac FooMain.java . When I run it with a maximum heap size of 5 million bytes, I get:

 java -Xmx5000000 FooMain total memory is: [5242880]. free memory is: [4901096]. max memory is: [5767168] 4878 1k arrays added. total memory is: [5767168]. free memory is: [543288]. max memory is: [5767168]. Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded at java.lang.String.toCharArray(String.java:2748) at java.util.Formatter$FormatSpecifier.print(Formatter.java:3048) at java.util.Formatter$FormatSpecifier.printInteger(Formatter.java:2744) at java.util.Formatter$FormatSpecifier.print(Formatter.java:2702) at java.util.Formatter.format(Formatter.java:2488) at java.util.Formatter.format(Formatter.java:2423) at java.lang.String.format(String.java:2792) at FooMain.memoryMsg(FooMain.java:7) at FooMain.main(FooMain.java:21) 

As long as the numbers are close enough, they don't seem very accurate (with the exception of total memory at the end, reaching exactly max memory ). In particular, 5368 arrays of 1000 bytes each should occupy more than 5,000,000 or even 5,242,880 bytes. How should these numbers be understood?

This is the java I am using:

 java version "1.7.0_80" Java(TM) SE Runtime Environment (build 1.7.0_80-b15) Java HotSpot(TM) Server VM (build 24.80-b11, mixed mode) 
+8
java java-7
source share
3 answers

is there an -Xmx hard limit?

It depends on what you mean by "hard." If you mean "cannot be changed by the program," then "Yes." If you mean "exact", then No. The sizes of the various spaces used by the garbage collector are a multiple of some power of 2 bytes. And, apparently, the JVM is rounded up, not down.

An example program that allocates 1000 byte arrays

How should these numbers be understood?

A 1000-byte Java array does not occupy exactly 1000 bytes:

  • There is an object header, including space for the 32-bit length field. (Usually 3 x 32 bits).

  • Heap nodes are allocated in multiples of 2 ^ N bytes. (Usually 2 ^ 3 == 8)


Then the question arises as to what causes OutOfMemoryError . You might think that this is because the heap is completely full. However, in this case, the message says that the upper limit of GC is exceeded. This means that the JVM has detected that the JVM is spending too much of the total processor time used by the garbage collector. What killed GC ... memory is not exhausted.

The rationale for the “GC upper limit” is that when the heap becomes full, the GC works often and restores less and less memory each time. When you fall into the “death spiral” in the GC, it’s better to quickly pull out the plug, rather than letting the application break its final point of failure.

In any case ... what does this mean that your heuristic to determine how much memory is allocated when the heap is full is probably incorrect.

+5
source share

Looking at the OpenJDK source code, the logic for determining the maximum heap size is quite complex and is determined by many variables. The actual heap size is set to hotspot/src/share/vm/memory/collectorPolicy.cpp , it uses the provided -Xmx value as input and aligns it using the following code:

 align_size_up(MaxHeapSize, max_alignment()); 

align_size_up is defined as:

 #define align_size_up_(size, alignment) (((size) + ((alignment) - 1)) & ~((alignment) - 1)) 

And max_alignment is the product of virtual memory page size and JVM garbage collection card size. The VM page size is 4096 bytes, and the card size is 512 bytes. Including these values ​​gives the actual MaxHeapSize of 6324224 bytes, which would be in good agreement with the numbers you see.

Note. I only looked briefly in the JVM code, so it’s possible that I missed something, but the answer seems to add up to what you see.

+6
source share

Other people largely answer your question, but out of interest I did the math :-)

It is indicated here:

This value must be a multiple of 1024 greater than 2 MB.

5,000,000 is not a multiple of 1024. I assumed that the argument is rounded to a multiple of 1024, which the rest of the answers confirm. Your total memory (which is more than just the declared heap space) is 5767168, which is 5632 * 1024 . It was increased at runtime from the initial 5242880 to match the growing heap area. Note that -Xmx declares a maximum, so it does not necessarily stand out immediately. Using this source, we can approximate the use of your memory (suppose 64 bits):

  • 4878000 bytes for bytes
  • 4878 * 24 = 117072 Disadvantages of a byte array
  • several bytes for other created objects and strings
  • slight memory hesitation due to garbage collection (at least the line you create for each iteration can be thrown away).

So, arrays occupy 4995072 bytes, which (coincidentally?) Would already be a multiple of 1024. But still overhead for other objects. Thus, the heap space is a multiple of 1024 greater than 4995072 and lower than 5767168. Given the free space at the end, this leaves us with 228808 bytes for the rest of the heap and non-heap memory, which sounds like a plausible number.

Finally, the word in free space remains at the end. The JVM does not necessarily fill all memory before a failure. If the memory is near completion, garbage collection works more often. If this takes a certain percentage of the total execution time, the JVM completes what happened in your case.

+1
source share

All Articles