java - 为什么 Java CMS 垃圾收集器不允许已用堆大小增长到可用堆大小?
问题描述
我正在测试 G1GC 和 CMS 垃圾收集器之间的差异。运行相同的程序会产生不同的堆大小使用(可能如预期)。
下图显示了 G1GC(左)与 CMS GC(右)的对比。G1GC 设法运行整个程序,而在使用 CMS 时,outOfMemoryException
会引发 an。
因此,我的问题是:为什么 CMS 不允许使用的堆大小达到可用的堆大小?当 10GB 可用时,堆大小在 8.00GB 时停止增长,并出现内存不足异常。
解决方案
简短的回答是,当堆填满时,CMS 不如 G1GC 那样管理内存。这是 CMS 被逐步淘汰的原因之一。
一个稍长一点的答案是 CMS 中 2GB 的未使用空间是为在 Eden 空间的次要(复制)GC 中疏散对象而保留的。相比之下,G1GC 似乎能够在 Tenured 空间填满时调整(缩小)Eden 空间。
请注意,这实际上可能是不切实际的基准测试的产物。在典型的应用程序中,次要集合将成功删除大部分新对象。在您的基准测试中,看起来几乎所有内容都是可访问的,因此分配的大多数对象最终都在 Tenured 空间中。
你能为这个做什么?
切换到 G1GC。在大多数情况下,CMS 更好。(最终您将别无选择。CMS 在 Java 9 中已被弃用,在 Java 14 中已被删除。)
您可以更改减小 Eden 空间的大小:具体调整 NewSize 和 MaxNewSize。然而,这对于正常的工作负载来说是不利的。这很容易导致年轻对象过早地被长期使用,这将增加 CMS 收集器的负载。
有一些较新的收集器旨在更好地处理“完整”堆。
推荐阅读
- git - SubGit:Git 钩子,如果未锁定,则锁定 svn 文件,如果被其他用户锁定,则拒绝提交
- java - org.graphstream.algorithm.APSP$APSPInfo.getShortestPathTo 处的 NullPointerException - 图形问题
- elasticsearch - 无法在索引上设置 index.mapping.single_type: true
- reactjs - 将数组数组作为道具传递
- django - 自定义 Django Channels 中间件在 Websocket 连接之前未完成处理
- linq - 如何为子对象列表配置 AutoMapper,以及如何在查询中使用 ProjectTo<>?
- php - 路由 [admin.distroyDish] 未定义。(查看:/home/abdalrazag/MyResutrant/resources/views/admin/manager.blade.php)
- python - 从 groupby 创建字典字典
- java - Kotlin 单元测试变量声明 lateinit vs lazy vs nullable vs non-nullable
- algorithm - 我在哪里可以找到用于类型推断的笛卡尔积算法的实现?