一尘不染

Java GC是否将内存释放回OS?

java

当垃圾收集器运行并释放内存时,该内存将返回操作系统,还是作为进程的一部分保留。我印象深刻的是,该内存实际上从未释放回OS,而是保留为内存区域/池的一部分,以供同一进程重用。

结果,进程的实际内存将永远不会减少。一篇使我想起的文章是Java的Runtime是用C / C ++编写的,所以我想同样的事情适用吗?

更新
我的问题是关于Java的。我之所以提到C / C ++,是因为我假设Java的分配/取消分配是由JRE使用某种形式的malloc / delete完成的


阅读 1135

收藏
2020-03-03

共1个答案

一尘不染

在热点JVM不释放内存给操作系统,但不会因为调整堆所以勉强是昂贵的,它假定,如果你需要的堆一旦你会再次使用它。

你可以通过设置使其更具侵略性,-XX:GCTimeRatio=19 -XX:MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=30从而使其在GC周期后花费更多的CPU时间来收集和限制已分配但未使用的堆内存量。

假设你正在使用并发收集器,还可以将-XX:InitiatingHeapOccupancyPercent=NN 设置为一个较低的值,以使GC几乎连续运行并发收集,这将消耗更多的CPU周期,但会更快地缩小堆。通常这不是一个好主意,但是在某些类型的具有大量备用CPU内核但内存不足的机器上,这是有道理的。

如果你使用的收集器具有默认的暂停时间目标(CMS或G1),则你也可以放宽该目标,以在收集器上设置更少的约束,或者你可以切换并行收集器,以在暂停时间之前优先考虑占用空间。

此外,通过Java 9 -XX:-ShrinkHeapInSteps选项,可以更积极地应用由前两个选项引起的缩小。相关的OpenJDK错误。

请注意,收缩能力和行为取决于所选择的垃圾收集器。例如,G1仅使用jdk8u20 获得了在堆中间退回未使用的块的能力,而ZGC 使用jdk13进行了回收,而ε收集器则极有可能不会这样做。
因此,如果需要堆收缩,则应该针对特定的JVM版本和GC配置进行测试。

GC Logging with PrintAdaptiveSizePolicy也可能提供洞察力,例如,当JVM尝试为年轻一代使用更多内存以满足某些目标时。

OpenJDK 12中还包含JEP 346,该JEP引入了带有G1PeriodicGCInterval选件的G1GC的即时内存释放,但又以一些额外的CPU为代价。它还提到了Shenandoah和OpenJ9 VM中的类似功能。

2020-03-03