jvm zgc 内存占用超出实际限制(内存占用3倍)

1. 现象

java服务使用jdk11 zgc垃圾回收,配置的堆大小为51G

-Xms51G  -Xmx51G  -Xss512k  -XX:MetaspaceSize=512m  -XX:MaxMetaspaceSize=512m

通过top服务查看,该java服务竟然在linux系统中占用157g内存

然而,此机器内存总大小只有64G,此时查看该机器内存如下所示:

此时产生疑惑:

为什么jvm进程内存占用远远超过配置的限额,同时为什么64G的内存机器能跑一个157G的进程,而且看起来机器内存还存在空余?

2. 原因

zgc使用不同视图进行gc工作:同一份内存,会映射到3种视图。ZGC借助内存映射,将多个地址映射到同一个内存文件描述符上,使得通过top查看进程内存,内存会膨胀3倍。

stackoverflow有对这一问题的说明:https://stackoverflow.com/questions/57899020/zgc-max-heap-size-exceed-physical-memory

Since this question was asked from time to time, and I am tired of explaining it already, let me try to put it here so people can simply search, get their answer, and be happy again (even for a very short period of time, it's still worth it!).

RSS over-reporting by ZGC is due to the technique that ZGC uses to manipulate the memory pages, namely, multi-mapping. and since ZGC is essentially another implementation of Zing C4 collector (by Azul Systems), Zing also shares the same "over-reporting" RSS issue.

Look into this code:

http://hg.openjdk.java.net/zgc/zgc/file/59c07aef65ac/src/hotspot/os_cpu/linux_x86/zPhysicalMemoryBacking_linux_x86.cpp#l160

Map all views:

    map_view(pmem, ZAddress::marked0(offset), AlwaysPreTouch);

    map_view(pmem, ZAddress::marked1(offset), AlwaysPreTouch);

    map_view(pmem, ZAddress::remapped(offset), AlwaysPreTouch);

This means that for the same address, ZGC will map it to 3 different views: marked0, marked1 and remapped. These 3 views are reflected int the virtual memory addresses. And this means, 3 different virtual memory addresses will be mapped to the same underlying physical memory, and thus for each physical memory page, there are 3 virtual pages mapped to it.

And if ZGC grows up to be a generational GC (where you have young generation and old generation, instead of one single generation as ZGC is right now), we can expect this number to be increased to 6x of xmx heap size too.

And this is why the multi-mapping used by both Azul Zing and Oracle ZGC put people to panic mode at "top" command. But please note that it is only the virtual memory space that gets reported, so unless your system tool runs into this confusing part, there is no reason for you to call 911.

另外:查看zgc进程,其虚拟内存占用一直是17T

ZGC使用41-0位记录对象地址,42位地址为应用程序提供了理论4TB的堆空间

45-42位为metadata比特位, 对应于如下状态: finalizable,remapped,marked1和marked0

46位为保留位,固定为0

63-47位固定为0

你可能感兴趣的:(jvm zgc 内存占用超出实际限制(内存占用3倍))