我有一个可能存在问题的应用程序可能存在内存泄漏问题。然而,在调查此问题的过程中,我发现了一些似乎相互矛盾的信息。
当我用来free
获取服务器上的内存使用情况摘要时,似乎有足够的可用 RAM:
[alice@myserver]$ free -h
total used free shared buff/cache available
Mem: 9.8G 2.4G 131M 3.6G 7.2G 3.5G
Swap: 0B 0B 0B
但是,如果我使用 top 来检查感兴趣的进程,它会显示单个进程使用了几乎所有的可用 RAM:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
16907 alice 20 0 158.6g 9.1g 7.6g S 63.2 92.8 6476:48 my_task
即使我计算所有的已用(2.4G)和共享(3.6G),也仍然只有 6.0G,比这个单个进程使用的 9.1G 少得多。
我相信哪一个,top
或者free
?
以下为一些相关附加详细信息:
- 操作系统是 CentOS 7.7
- my_task 是一个运行 JDK 15 的 Java 应用程序,中关村
- my_task 使用 JNI 并分配了大量堆外内存(预计为 1-2GB,而不是 4 或 5GB)
- 最大堆大小为 3GB,但 VisualVM 显示总堆大小约为 2GB,仅分配了约 1GB
答案1
事实证明top
这是错误的,这是由于 ZGC 造成的。
为了避免掩码指针的开销,ZGC 采用了多重映射技术。多重映射是将多段虚拟内存映射到同一段物理内存。
ZGC使用Java堆的3个视图(“marked0”,“marked1”,“remapped”),即3种不同“颜色”的堆指针和同一个堆的3个虚拟内存映射。
因此,操作系统可能会报告内存使用量增加了 3 倍。
https://stackoverflow.com/questions/57899020/zgc-max-heap-size-exceed-physical-memory https://stackoverflow.com/questions/62926652/the-java-zgc-garbage-collector-uses-a-lot-of-memory