当前位置: 首页 > 知识库问答 >
问题:

GC是否将内存释放回OS?

充普松
2023-03-14

当垃圾收集器运行并释放内存时,内存会返回操作系统还是作为进程的一部分保留下来。我的强烈印象是,内存实际上从未释放回操作系统,而是作为内存区域/池的一部分保留下来,供同一进程重复使用。

因此,进程的实际内存永远不会减少。提醒我的一篇文章是这样的,Java的运行时是用C/C写的,所以我想同样的事情也适用?

更新< br >我的问题是关于Java的。我提到C/C是因为我假设Java的分配/释放是由JRE使用某种形式的malloc/delete来完成的

共有3个答案

齐琦
2023-03-14

如果您使用G1收集器并偶尔调用System.gc()(我每分钟调用一次),Java将可靠地收缩堆并将内存返回给操作系统。

由于Java 12,如果应用程序处于空闲状态,G1会自动执行此操作。

我建议将这些选项与上述建议结合使用,以获得非常紧凑的常驻过程尺寸:

-XX:+UseG1GC -XX:MaxHeapFreeRatio=30 -XX:MinHeapFreeRatio=10

几个月来,我每天都在一个大型应用程序(一个完整的基于Java的客户操作系统)中使用这些选项,动态地加载和卸载类,Java进程几乎总是保持在400到800 MB之间。

毕富
2023-03-14

在某些情况下,JVM确实会释放回内存,但是(出于性能原因)每当对一些内存进行垃圾收集时,这种情况不会发生。它还依赖于JVM、操作系统、垃圾收集器等。你可以使用JConsole、VisualVM或其他分析器来观察应用程序的内存消耗。

另请参阅此相关错误报告

邰钟展
2023-03-14

HotSpot JVM确实将内存释放回操作系统,但这样做是不情愿的,因为调整堆的大小很昂贵,并且假设如果您需要该堆一次,您将再次需要它。

一般来说,收缩能力和行为取决于所选择的垃圾收集器,即JVM版本,因为收缩能力通常是在添加GC之后很久才在以后的版本中引入的。一些收集器可能还需要传递附加选项来选择收缩。有些很可能永远不会支持它,例如EpsilonGC。因此,如果需要堆收缩,应该针对特定的JVM版本和GC配置进行测试

在这些版本中没有提示内存回收的明确选项,但是您可以通过设置-XX: GCTimeRatio=19-XX: MinHeapFreeRatio=20-XX: MaxHeapFreeRatio=30来使GC更具侵略性,这将允许它在GC周期后花费更多的CPU时间来收集和限制已分配但未使用的堆内存量。

如果您使用的是并发收集器,您还可以将-XX: LaunatingHeap占领百分比=N设置为某个较低的值,以使GC几乎连续运行并发收集,这将消耗更多的CPU周期,但会更快地缩小堆。这通常不是一个好主意,但在某些类型的机器上,有很多备用CPU内核但内存不足,这是有意义的。

如果您正在使用G1GC,请注意,jdk8u20只能在堆的中间返回未使用的块,早期版本只能在堆的末尾返回块,这极大地限制了可以回收多少块。

如果您使用的是具有默认暂停时间目标(例如 CMS 或 G1)的收集器,则还可以放宽该目标以对收集器施加更少的约束,或者您可以切换到并行收集器以优先于占用空间而不是暂停时间。

为了验证收缩是否发生或诊断GC决定不收缩的原因,您可以使用GC日志记录-XX:PrintAdaptiveSizePolicy也可以提供洞察力,例如,当JVM试图为年轻一代使用更多内存以实现某些目标时。

添加了-XX:-ShrinkHeapInSteps选项,可用于更积极地应用上一节中提到的选项导致的收缩。相关OpenJDK错误。

对于日志记录-XX:PrintAdaptiveSizePolicy已替换为-Xlog:gc-ergo

引入了通过G1periodicGCInterval(JEP 346)为G1GC启用提示内存释放的选项,同样以牺牲一些额外的CPU为代价。JEP还提到了谢南多亚和OpenJ9虚拟机中的类似功能。

为ZGC添加类似的行为,在本例中默认启用。此外,XXSoftMaxHeapSize对某些工作负载有帮助,可以将平均堆大小保持在某个阈值以下,同时仍允许出现瞬态峰值。

 类似资料:
  • 问题内容: 当垃圾收集器运行并释放内存时,该内存将返回操作系统,还是作为进程的一部分保留。我印象深刻的是,该内存实际上从未释放回OS,而是保留为内存区域/池的一部分,以供同一进程重用。 结果,进程的实际内存将永远不会减少。一篇使我想起的文章是Java的Runtime是用C / C ++编写的,所以我想同样的事情适用吗? 更新 我的问题是关于Java的。我之所以提到C / C ++,是因为我假设Ja

  • 问题内容: 在Java运行时中,如果我的应用程序释放了内存,运行时是否将内存释放回OS?还是回到我的过程? 问题答案: 这取决于JVM的实现,在规范中未指定。 作为第一步,Sun JVM将保留它。一旦未使用一定比例(可配置)的已分配内存,它将将其中一部分返回给OS(行为受和设置影响)。

  • 我在C#上度过了一段糟糕的时光,在我不再引用它之后,没有为我保存在内存中的大型结构释放内存。 我在下面包含了一些代码,它们显示了与我遇到的问题类似的问题。我想我一定是误解了GC,因为我不确定为什么下面的代码会抛出内存不足异常。 有人知道为什么我包含的代码会丢失内存吗?没有一份名单被保留,可以立即清理。 谢谢, 保罗 复制:全新的4.5控制台应用程序,将代码粘贴到Main中。 异常将在for循环的第

  • 在阅读了一些像这样的答案和JEP-346之后,我意识到G1确实会将内存释放回操作系统。 然而,它是否将内存释放回操作系统,即使当前内存使用可能低于初始堆内存(即在此JEP之前,在我的案例中为JDK11)? 假设我有一个Java11 VM,运行和设置为,在RAM上,但是我只消耗大约。G1会释放足够的内存回操作系统吗? 我在任何地方都没有找到任何文档说明G1仅限于在发布时考虑Xms阈值。 我在生产过程

  • 我正在为我的应用程序使用GC选项。 由于大多数人都已经体验过JVM擅长将堆增加到最大堆大小,但它不会将内存释放回操作系统。我遇到了