GC是否将内存释放回操作系统?

Jim*_*Jim 36 java garbage-collection memory-management

当垃圾收集器运行并释放内存时,此内存会返回到操作系统,或者它是否作为进程的一部分保留.我的印象是,内存从未实际发布回操作系统,而是作为内存区/池的一部分保留,以便由同一进程重用.

结果,进程的实际内存永远不会减少.一篇提醒我的文章这篇文章和Java的Runtime是用C/C++编写的,所以我想同样的事情适用于此?

更新
我的问题是关于Java.我提到C/C++,因为我假设Java的分配/解除分配是由JRE使用某种形式的malloc/delete完成的

the*_*472 52

热点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 在堆中间回收未使用的块的能力.

因此,如果需要堆缩小,则应针对特定的JVM版本和GC配置进行测试.

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

还有一个JEP草案让G1更加热切地回报记忆,但作为草案,不确定是否以及何时实施.它还提到了Shenandoah和具有这种能力的OpenJ9 VM.


lba*_*scs 9

在某些情况下,JVM确实释放了内存,但是(出于性能原因)只要某些内存被垃圾收集,就不会发生这种情况.它还取决于JVM,操作系统,垃圾收集器等.您可以使用JConsole,VisualVM或其他分析器来监视应用程序的内存消耗.

另请参阅此相关错误报告

  • 我只是验证了,我已经看到它回馈了一些记忆!在Windows上我喜欢使用vmmap应用程序(可以从Microsoft免费下载),它可以让你看到很多关于进程内存使用情况的有趣信息. (2认同)

Ste*_*ich 8

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

从 Java 12 开始,如果应用程序空闲,G1 会自动执行此操作。

我建议将这些选项与上述建议结合使用,以获得非常紧凑的驻留进程大小:

-XX:+UseG1GC -XX:MaxHeapFreeRatio=30 -XX:MinHeapFreeRatio=10
Run Code Online (Sandbox Code Playgroud)

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


fra*_*sti 3

本文解释了 Java 7 中 GC 的工作原理。简而言之,有许多不同的垃圾收集器可用。通常,内存是为 Java 进程保留的,只有一些 GC 将其释放给系统(我认为是根据请求)。但是,Java 进程使用的内存不会无限期地增长,因为 Xmx 选项定义了一个上限(通常为 256m,但我认为它取决于操作系统/机器)。