问题
I have machine with 16G RAM. I run a java application with arguments -Xms9G -Xmx9G
.
When I run top
command I see that my java process is taking 13.8g VIRT, but only 4.6g of RES.
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
5019 root 20 0 13.8g 4.7g 18m S 0.7 30.7 3:28.39 java
On running pmap
command, I see that only ~3.9g of heap is present as RES, rest 5.7g is in virtual.
Address Kbytes RSS Dirty Mode Mapping
0000000580000000 9452384 4074228 4074228 rw--- [ anon ]
Upon monitoring HPCUR with jvmtop
, I observe that the GC is triggered when the HPCUR reaches about 3g.
PID MAIN-CLASS HPCUR HPMAX NHCUR NHMAX CPU GC VM USERNAME #T DL
5019 .1-SNAPSHOT.jar 408m 9216m 192m n/a 0.25% 0.00% O8U20 webapp 823
I observe that the RES for the process increases gradually, heap memory in RES (by pmap) also increases gradually too. As a result GC threshold increases.
I have several questions about this behavior.
- Is only the heap that is present in RES used, and not the VIRT?
- If I have allotted 9G min heap (
-Xms
), then initially why only 3.9g RES is allotted. Isn't this same as keeping -Xms low? What is the point of keeping -Xms=-Xmx then? - On what basis is it decided that how much heap should be in RES? Read somewhere that its managed by OS, but any rough logic?
- Any way to make sure, that the allotted heap is actually used?
回答1:
- Yes HEAP is RES (as long as it fits in main memory)
- This answer suggests that
-Xms
is a hint to GC at what point a full garbage collection is necessary. Testing with my local JVM I can confirm that it does not immediately reserve the memory. What you gain is that your JVM does not block a lot of unused memory but will reach you lower bound faster as there are less GC runs. - Answered by 1. : RES always contains all of HEAP
- My understanding is that your options will achieve what you intend to. Your application will grab 9GB of memory and then start garbage collection more frequently. There are other options like
MinHeapFreeRatio
and options that depend on the gargbage collector used if you need more optimization.
Did you print GC logs and verify that something is wrong? If you see a lot of GC runs on application startup before 9G is reached I would look further. If there is hardly any GC run before hitting 9G I would say everything is fine.
回答2:
VIRT
denotes Virtual memory - this is the entire reserved address space of the process.RSS
is the resident set size - the portion of the virtual address space allocated in physical RAM. For any address range (not only the heap)RSS
is the subset ofVIRT
, possibly complete or empty. Seems like you already exploredpmap
- for each virtual address range it shows the exact amount of physically allocated memory (RSS).- OS allocates physical pages lazily on the first access. That's why even committed memory is not the part of RSS until the corresponding pages are read or written to. The fact that the large portion of heap is not in RSS means that this part of the heap has never been touched. See also this question.
- There is a JVM option
-XX:+AlwaysPreTouch
that forcibly touches every page of the heap thus making it the part of RSS. Tryjava -Xms9G -Xmx9G -XX:+AlwaysPreTouch
.
来源:https://stackoverflow.com/questions/56334831/how-is-it-decided-that-how-much-physical-memory-is-to-be-allocated-to-java-heap