I have a very simple web server class (based on Java SE's HttpServer
class).
When I start the compiled class using this command to put limits on memory usage:
java -Xmx5m -Xss5m -Xrs -Xint -Xbatch Test
Now if I check memory using top
command, it indicates ~31MB of resident memory is used by the Java process which executes my class.
I was wondering what is that 30MB used for?
Some of you have been there. You have added -Xmx option to your startup scripts and sat back relaxed knowing that there is no way your Java process is going to eat up more memory than your fine-tuned option had permitted. And then you were in for a nasty surprise.
From that list, the command-line arguments specifically related to Java application memory use are: Digging around, I just found this additional Java xms, xmx, and xmn information on Apple's web site: -Xms size in bytes Sets the initial size of the Java heap.
Here you can see the -Xmx to supported in java 10 version in the container world: Max. Heap Size: 512.00M What Are the Limitations? a. If you are going to allocate ‘-Xmx’ more than the container’s memory size, then your application will experience ‘java.lang.OutOfMemoryError: kill process or sacrifice child.’
If you are going to allocate ‘-Xmx’ more than the container’s memory size, then your application will experience ‘java.lang.OutOfMemoryError: kill process or sacrifice child.’
As the comments and answers have alluded to, there are a number of other factors to take into account when measuring JVM memory usage. However, I don't think any answer has gone into nearly enough depth.
Lets hit the question "I was wondering what is that 30MB used for?" head on. To do this, here is a simple java class:
// HelloWorld.java
public class HelloWorld {
public static void main(String[] args) throws Exception {
System.out.println("Hello world!");
Thread.sleep(10000); // wait 10 seconds so we can get memory usage
}
}
Now compile and run it with heap constraints:
$ nohup java -Xms2m -Xmx2m HelloWorld & # run in background
$ ps aux | awk 'NR==1; /[H]elloWorld/'
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
chaospie 6204 6.0 0.1 2662860 23040 pts/2 Sl 19:15 0:00 java -Xms2m -Xmx2m HelloWorld
Looking at the RSS (Resident Set Size, or how much memory this process is using) above we see that the JVM's
process is using about 23MB of memory. To see why, lets do some analysis. The quickest way to get a good
overview is to turn on NativeMemorytracking
use the jcmd
tool's VM.native_memory
command. So,
let's run our app again:
$ nohup java -XX:NativeMemoryTracking=summary -Xms2M -Xmx2M HelloWorld &
[2] 6661
nohup: ignoring input and appending output to 'nohup.out'
$ ps aux | awk 'NR==1; /[H]elloWorld/'
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
chaospie 6661 5.0 0.1 2662860 23104 pts/2 Sl 19:21 0:00 java -XX:NativeMemoryTracking=summary -Xms2M -Xmx2M HelloWorld
$ jcmd 6661 VM.native_memory summary
6661:
Native Memory Tracking:
Total: reserved=1360145KB, committed=61177KB
- Java Heap (reserved=2048KB, committed=2048KB)
(mmap: reserved=2048KB, committed=2048KB)
- Class (reserved=1066093KB, committed=14189KB)
(classes #402)
(malloc=9325KB #146)
(mmap: reserved=1056768KB, committed=4864KB)
- Thread (reserved=20646KB, committed=20646KB)
(thread #21)
(stack: reserved=20560KB, committed=20560KB)
(malloc=62KB #110)
(arena=23KB #40)
- Code (reserved=249632KB, committed=2568KB)
(malloc=32KB #299)
(mmap: reserved=249600KB, committed=2536KB)
- GC (reserved=10467KB, committed=10467KB)
(malloc=10383KB #129)
(mmap: reserved=84KB, committed=84KB)
- Compiler (reserved=132KB, committed=132KB)
(malloc=1KB #21)
(arena=131KB #3)
- Internal (reserved=9453KB, committed=9453KB)
(malloc=9421KB #1402)
(mmap: reserved=32KB, committed=32KB)
- Symbol (reserved=1358KB, committed=1358KB)
(malloc=902KB #86)
(arena=456KB #1)
- Native Memory Tracking (reserved=143KB, committed=143KB)
(malloc=86KB #1363)
(tracking overhead=57KB)
- Arena Chunk (reserved=175KB, committed=175KB)
(malloc=175KB)
Let's break it down 1:
stack
in this section reflects the Xss
value times the number of threads, you can get the default -Xss
value with java -XX:+PrintFlagsFinal -version |grep ThreadStackSize
).Much more than just the heap!
Note that each region has a committed
and a reserved
section. To keep it short
reserved
is what it can grow to and committed
is what is currently committed to be used.
For example see the Java Heap
section: Java Heap (reserved=2048KB, committed=2048KB)
, reserved
is our
-Xmx
value and committed would be our -Xms value
, in this case they are equal .
Note too that the total committed
size - it does not
reflect actual usage reported by RSS (or the RES column in top
). The reason they differ is that RSS shows
the size of all memory pages which have been, and still are in use in physical memory, whereas committed
shows the memory which is
used including that which is not in physical memory 3.
There is a lot more to this, however JVM and OS memory management is a complex topic, so I hope this answers your question at least at a high level.
Arena is a chunk of memory allocated using malloc. Memory is freed from these chunks in bulk, when exiting a scope or leaving an area of code. These chunks may be reused in other subsystems to hold temporary memory, for example, pre-thread allocations. Arena malloc policy ensures no memory leakage. So Arena is tracked as a whole and not individual objects. Some amount of initial memory can not by tracked.
Java runs on a virtual machine, rather than directly on your hardware. This means that this machine needs its own memory to run. The 5MB you allowed your program likely means that there is another 26MB being used by the Java Virtual Machine (JVM).
-Xmx5m is only used for heap memory, top will show you the entire memory including native memory used by JNI calls handled within the process.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With