【ZGC】关于JVM新一代垃圾回收器会占用大量内存的问题
本文除开文献或文章引用外,其他容版权归本人所有。任何人或团体、机构全部转载或者部分转载、摘录,请保留本博客链接或标注来源!近期,我使用了最新的JDK15。关于15的新特性这里就不说了,重点在于被传的神乎其神的新一代垃圾回收器ZGC。ZGC作为新一代垃圾回收器,拥有低延迟、归还内存给操作系统等等特点,具体在这里就不在多讲了。
回归正题,我在使用ZGC时发现了一个问题,就是内存占用过大的问题,特别是对比G1,ZGC的内存占用竟然至少多了两倍!也就是基本上ZGC的内存占用是G1的三倍以上! 三倍以上,这是什么概念,虽然现代经济与科学飞速发展,硬件瓶颈已经很少出现,但是对于我这种穷逼来说,买一台1H2G的服务器已经很不错了。更何况,当初就是冲着ZGC能归还内存给操作系统才踏入了这个坑里,那么这么低的硬件配置肯定没法支撑ZGC了,毕竟内存就那么点。 于是为了证明这个内存占用过大的问题不是偶然,我在本地创建了一台Windows server 2019的虚拟机,在内运行了java应用并查看了内存占用情况,如图下图:
可以看到JVM的占用内存和系统报告的实际内存不一样。这就非常奇怪了,我尝试换回了G1垃圾收集器再次测试,如下图: 好吧结果显而易见了,确实是ZGC的锅。 但是为什么呢?ZGC为什么占用了如此大的内存?对于我这个好奇心极强的人来说,不查清楚原因就像是拉屎被人打断一样难受。
我去了over stack,找到了一篇类似的问题"The Java ZGC garbage collector USES a lot of memory",然后下翻找到了这样的回答: "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."
我来简单解释一下这是什么意思,就是说ZGC使用了"染色指针"这一多重映射技术,其中堆内存分为了"marked0", "marked1", "remapped"三种堆视图,最后就会导致系统报告的内存为原本的三倍以上, 注意:多映射影响系统报告的内存使用结果,但物理上堆仍然会使用一倍的内存。在windows上表现会极为明显,但目前本人在linux使用JDK16+ZGC时,通过TOP查看报告时,只有虚拟内存占用报告异常,系统也没有因此去使用虚拟内存,物理占用是正常的1倍(此时时间为2021年)。这是吞吐量-延迟-内存占用折衷的结果,有取有舍,ZGC是具有低暂停时间的并发GC,在对比G1运行时,ZGC回收垃圾会极为迅速但是也会占用更多的CPU时间。所以,如果想要低延迟请选择ZGC,如果想要高吞吐量还是选择G1.如果您的服务器计算资源足够,那么我推荐你选择更为强大的ZGC.
2020年11月30日 14:28Felix 测试回复 IzayoiFly 发表于 2021-1-17 02:51
测试回复
? 2021年最后一次更新内容{:5_118:}
页:
[1]