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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30458195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 17:09:29  来源:igfitidea点击:

Does GC release back memory to OS?

javamemory-managementgarbage-collection

提问by Jim

When the garbage collector runs and releases memory does this memory go back to the OS or is it being kept as part of the process. I was under the strong impression that the memory is never actually released back to OS but kept as part of the memory area/pool to be reused by the same process.

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

As a result the actual memory of a process would never decrease. An articlethat reminded me was this and Java's Runtime is written in C/C++ so I guess the same thing applies?

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

Update
My question is about Java. I am mentioning C/C++ since I assume the Java's allocation/deallocation is done by JRE using some form of malloc/delete

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

回答by the8472

The HotSpot JVMdoes release memory back to the OS, but does so reluctantly since resizing the heap is expensive and it is assumed that if you needed that heap once you'll need it again.

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

You can make it more aggressive by setting -XX:GCTimeRatio=19 -XX:MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=30which will allow it to spend more CPU time on collecting and constrain the amount of allocated-but-unused heap memory after a GC cycle.

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

Assuming you're using a concurrent collector you can also set -XX:InitiatingHeapOccupancyPercent=Nwith N to some low value to let the GC run concurrent collections almost continuously, which will consume even more CPU cycles but shrink the heap sooner. This generallyis not a good idea, but on some types of machines with lots of spare CPU cores but short on memory it can make sense.

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

If you're using a collector with a default pause time goal (CMS or G1) you can also relax that goal to place fewer constraints on the collector, or you can switch go the parallel collector to prioritize footprint over pause times.

如果您使用具有默认暂停时间目标(CMS 或 G1)的收集器,您还可以放宽该目标以减少对收集器的限制,或者您可以切换并行收集器以优先考虑占用空间而不是暂停时间。

Additionally with Java 9 -XX:-ShrinkHeapInStepsoption can be be used to apply the shrinking caused by the previous two options more aggressively. Relevant OpenJDK bug.

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

Do note that shrinking ability and behavior depends on the chosen garbage collector. For example G1 only gained the ability to yield back unused chunks in the middle of the heapwith jdk8u20, while ZGC did with jdk13and the epsilon collector most likely never will.
So if heap shrinking is desired it should be tested for a particular JVM version and GC configuration.

请注意,收缩能力和行为取决于选择的垃圾收集器。例如,G1 仅通过jdk8u20获得了在堆中间回收未使用块的能力,而 ZGC使用 jdk13 实现了,而 epsilon 收集器很可能永远不会。
因此,如果需要堆收缩,则应针对特定的 JVM 版本和 GC 配置进行测试。

GC Logging with PrintAdaptiveSizePolicymay also provide insight, e.g. when the JVM tries to use more memory for the young generation to meet some goals.

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

There also is JEP 346, included in OpenJDK 12, which introduces prompt memory release for G1GC with the G1PeriodicGCIntervaloption, again at the expense of some additional CPU. It also mentions similar features in Shenandoahand the OpenJ9 VM.

还有JEP 346,包含在 OpenJDK 12 中,它为 G1GC 引入了快速内存释放G1PeriodicGCInterval选项,同样以一些额外的 CPU 为代价。它还提到了ShenandoahOpenJ9 VM中的类似功能。

回答by lbalazscs

The JVM does release back memory under some circumstances, but (for performance reasons) this does not happen whenever some memory is garbage collected. It also depends on the JVM, OS, garbage collector etc. You can watch the memory consumption of your app with JConsole, VisualVM or another profiler.

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

Also see this related bug report

另请参阅此相关错误报告

回答by Stefan Reich

If you use the G1 collector and call System.gc() occasionally (I do it once a minute), Java will reliably shrink the heap and give memory back to the OS.

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

Since Java 12, G1 does this automatically if the application is idle.

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

I recommend using these options combined with the above suggestion for a very compact resident process size:

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

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

Been using these options daily for months with a big application (a whole Java-based guest OS) with dynamically loading and unloading classes - and the Java process almost always stays between 400 and 800 MB.

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

回答by francesco foresti

this article hereexplains how the GC work in Java 7. In a nutshell, there are many different garbage collectors available. Usually the memory is kept for the Java process and only some GCs release it to the system (upon request I think). But, the memory used by the Java process will not grow indefinitely, as there is an upper limit defined by the Xmx option (which is 256m usually, but I think it is OS/machine dependant).

本文在这里介绍了如何在Java 7中的GC工作简单地说,有许多可供不同的垃圾收集器。通常,内存是为 Java 进程保留的,只有一些 GC 将其释放给系统(我认为应请求)。但是,Java 进程使用的内存不会无限增长,因为 Xmx 选项定义了一个上限(通常为 256m,但我认为它取决于操作系统/机器)。

回答by Макс Даниленко

ZGCreleased in 13 java and it can return unused heap memory to the operating system Please see the link

13 java中发布的ZGC可以将未使用的堆内存返还给操作系统请看链接