问题描述
我使用Springboot构建了一个简单的应用程序.部署到Linux服务器时使用的ZGC垃圾收集器使用大量内存..我试图通过Xmx500m将最大堆内存限制为500MB,但是JAVA程序仍然使用了更多内存超过1GB.当我使用G1收集器时,它仅使用了350MB.我不知道为什么,这是JDK11的BUG吗?还是我的引导参数有问题?####运行时环境
- 操作系统: CentOS Linux 7.8.2003版
- JDK版本: jdk11
- springboot版本: v2.3.0.RELEASE 这是我的Java启动命令
java -Xms128m -Xmx500m \
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC \
-jar app.jar
以下是运行时内存使用情况的屏幕截图
堆内存使用量 https://github.com/JoyfulAndSpeedyMan/assets/blob/master/2020-07-13%20201259.png?raw = true
系统内存使用量 https://github.com/JoyfulAndSpeedyMan/assets/blob/master/2020-07-13%20201357.png?raw = true
这是使用默认垃圾收集器时发生的事情 Java启动命令
java -Xms128m -Xmx500m \
-jar app.jar
堆内存使用量 https://github.com/JoyfulAndSpeedyMan/assets/blob/master/2020-07-13%20202442.png?raw = true
系统内存使用量 https://github.com/JoyfulAndSpeedyMan/assets/blob/master/2020-07-13%20202421.png?raw = true
默认情况下,jdk11使用G1垃圾收集器.从理论上讲,G1是否不应该比ZGC占用更多的内存?为什么我不这样使用G1?我误会了吗?因为我是JVM的初学者,所以我不明白为什么.
ZGC采用了称为彩色指针的技术.这个想法是在堆中使用64位指针中的一些空闲位来嵌入元数据.但是,在取消引用此类指针时,需要屏蔽这些位,这意味着JVM需要做一些额外的工作.
为避免掩盖指针的开销,ZGC涉及了 multi-mapping 技术.多映射是指将多个范围的虚拟内存映射到同一范围的物理内存.
ZGC使用Java堆的3个视图(标记为0",标记为1",重新映射"),即3种不同的颜色"视图.同一堆的堆指针和3个虚拟内存映射的集合.因此,操作系统可能会报告内存使用量是原来的3倍.例如,对于512 MB的堆,所报告的已提交内存可能高达1.5 GB,不计算内存.注意:多重映射会影响报告的使用的内存,但是从物理上讲,堆仍将使用512 MB的RAM.有时这会导致有趣的效果,即该过程的RSS看起来大于物理RAM .另请参阅:
I built a simple application using Springboot.The ZGC garbage collector I use when deploying to a Linux server USES a lot of memory..I tried to limit the maximum heap memory to 500MB with Xmx500m, but the JAVA program still used more than 1GB. When I used the G1 collector, it only used 350MB.I don't know why, is this a BUG of JDK11?Or do I have a problem with my boot parameters?####Runtime environment
- operating system: CentOS Linux release 7.8.2003
- JDK version: jdk11
- springboot version: v2.3.0.RELEASEHere is my Java startup command
java -Xms128m -Xmx500m \
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC \
-jar app.jar
Here is a screenshot of the memory usage at run time
Heap memory usagehttps://github.com/JoyfulAndSpeedyMan/assets/blob/master/2020-07-13%20201259.png?raw=true
System memory usagehttps://github.com/JoyfulAndSpeedyMan/assets/blob/master/2020-07-13%20201357.png?raw=true
Here's what happens when you use the default garbage collectorJava startup command
java -Xms128m -Xmx500m \
-jar app.jar
Heap memory usagehttps://github.com/JoyfulAndSpeedyMan/assets/blob/master/2020-07-13%20202442.png?raw=true
System memory usagehttps://github.com/JoyfulAndSpeedyMan/assets/blob/master/2020-07-13%20202421.png?raw=true
By default jdk11 USES the G1 garbage collector. Theoretically, shouldn't G1 be more memory intensive than ZGC?Why didn't I use it that way?Did I misunderstand?Since I'm a beginner to the JVM, I don't understand why.
ZGC employs a technique known as colored pointers. The idea is to use some free bits in 64-bit pointers into the heap for embedded metadata. However, when dereferencing such pointers, these bits need to be masked, which implies some extra work for the JVM.
To avoid the overhead of masking pointers, ZGC involves multi-mapping technique. Multi-mapping is when multiple ranges of virtual memory are mapped to the same range of physical memory.
ZGC uses 3 views of Java heap ("marked0", "marked1", "remapped"), i.e. 3 different "colors" of heap pointers and 3 virtual memory mappings for the same heap.
As a consequence, the operating system may report 3x larger memory usage. For example, for a 512 MB heap, the reported committed memory may be as large as 1.5 GB, not counting memory besides the heap. Note: multi-mapping affects the reported used memory, but physically the heap will still use 512 MB in RAM. This sometimes leads to a funny effect that RSS of the process looks larger than the amount of physical RAM.
See also:
- ZGC: A Scalable Low-Latency Garbage Collector by Per Lidén
- Understanding Low Latency JVM GCs by Jean Philippe Bempel
这篇关于Java ZGC垃圾收集器使用大量内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!