java - GC1 不释放 OS-Memory
问题描述
我使用默认垃圾收集器 (G1GC) 运行 java 应用程序。我不明白 G1CC 何时准确释放内存。在htop
我看到700M
应用程序使用的地方。在我这样做之后,jcmd <pid> GC.run
它下降到大约250M
. 这是否意味着 GC 自己不会这样做?
解决方案
在优化应用程序的性能和可扩展性时,资源效率是一个主要问题。在 Java 世界中,通常支配资源问题的一个方面是内存使用——更具体地说,是 Java 堆的大小。
与 .NET 和 CLR 相比,JVM 以需要在启动时调整堆大小而闻名,而没有任何空间回收的机会,这将使资源可用于其他进程。这在今天仍然适用吗?让我们来了解一下。
垃圾收集器负责管理堆和相关的操作系统分配。从 JDK 9 开始,G1 垃圾收集器一直是默认的 GC。一般来说,GC 会尽量避免释放堆空间(以将内存还给操作系统),因为如果稍后需要该空间,这可能会导致性能下降。
堆收缩取决于回收周期,回收周期由 Young-only 和空间回收阶段组成。
如果相关的伊甸园空间(最初分配新对象的地方)用尽了,就会发生仅限年轻阶段。可达对象被疏散(移动)到幸存者空间。如果幸存者空间耗尽,可达对象将被疏散到另一个幸存者空间或老年代(如果对象是可达的或“存活”给定数量的集合)。
空间回收取决于老年代的大小,由初始堆占用百分比 (IHOP) 控制。默认 ( -XX:InitiatingHeapOccupancyPercent
) 为 45%,但 IHOP 由 GC 调整以优化收集间隔(称为“自适应 IHOP”)。这个阶段也处理年轻代,因此它被称为“混合收集”。
根据JDK 9 中的 G1 源,收缩仅在完全收集(显式收集与否)之后进行,并且仅在满足特定阈值的情况下进行。G1CollectedHeap::do_full_collection
调用G1CollectedHeap::resize_if_necessary_after_full_collection
,它处理收缩过程并生成以下 GC 日志输出:
log_debug(gc, ergo, heap)(
"Shrink the heap. requested shrinking amount: "
SIZE_FORMAT "B aligned shrinking amount: "
SIZE_FORMAT "B attempted shrinking amount: "
SIZE_FORMAT "B",
shrink_bytes, aligned_shrink_bytes, shrunk_bytes);
G1 GC 旨在
[...] 提供延迟和吞吐量之间的最佳平衡 [...]
G1 尝试尽可能长时间地推迟垃圾收集,并尝试避免完全垃圾收集。有关详细信息,请参阅垃圾回收周期。
[...] 如果应用程序在收集活跃度信息时内存不足,G1 会像其他收集器一样执行就地停止世界全堆压缩 (Full GC) [...]
除非手动触发(例如使用java.lang.System.gc()
),否则收集器仅在空间耗尽的情况下执行完整收集。这就是堆收缩可能发生的时候。
根据JDK 15 中的 G1 源代码,对完整集合以及并发标记和清除集合进行了收缩。依次G1FullCollector::complete_collection
调用. 实际收缩过程和日志消息与 JDK 9 相同。与 JDK 9 相比,JDK 12 及更高版本还在所谓的重新标记阶段(调用)期间,在正常收集周期的上下文中执行收缩。G1CollectedHeap::prepare_heap_for_mutators
G1CollectedHeap::resize_heap_if_necessary
G1ConcurrentMark::remark
G1CollectedHeap::resize_heap_if_necessary
更改是通过08041b0d7c08引入的。
一种直接的监控方法是-verbose:gc
。用于-Xlog:gc=debug
查看上面提到的日志输出,以防缩水。
因此,尽管普遍认为,JVM 确实会将内存返回给操作系统。在 JDK 11 之前,堆收缩仅在完全收集后才会触发,因为更改的重要性足以保证该操作不会影响性能。使用 JDK 12+(检查到 15),堆收缩也会在正常收集周期内触发,这使得通常不涉及完整收集的应用程序更有可能看到堆收缩。
推荐阅读
- sql - 在给定条件下评估连续日期
- qt - Ubuntu 上的 Qt 和 OpenSSL 不兼容版本
- vba - 从网页视图源中搜索特定文本并使用 VBA 宏复制完整的完整行
- python - 芹菜工人 ImportError:没有名为“项目”的模块
- c - 如何从 C 程序中使用 OCIServerVersion (Oracle)?
- r - 治疗前后测量的 Wilcox.test
- python - 如何将networkX图导入neo4j?
- apache-spark - 不允许 EMR Master SSH
- javascript - 通过某些表单验证来防止 ajax 调用
- php - PHP json_encode 既漂亮又非转义