ChatGPT解决这个技术问题 Extra ChatGPT

Does GC release back memory to OS?

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 article that reminded me was this and Java’s Runtime is written in C/C++ so I guess the same thing applies?

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

Even using the standard heap allocation methods in C or C++ doesn't have to release back to the OS, and the OS can itself keep the freshly unallocated pages mapped to the process (so it doesn't seem to be free'd).
Java’s Runtime is written in C/C++ so I guess the same thing applies? And Java´s GC is written in C++ too... it´s not "below" C++
Till now no heap memory is released to the OS. Merely memory is taken extra if the max heap size still is not reached. This is the same as in C, whereas C has the additional problem that memory reuse is a bit hampered with memory fragmentation (though C can do its own memory management of allocs).
JVM starts with a minimum heap size and we may set max and minimum heap-size to the same value. If max and min heap size is same, it will upfront allocate the JAVA heap and there actually may only few Java objects using this heap, in this case GC doesn't release memory back to OS. GC actually claims back memory used be un-referenced objects, so that they may used for other objects. It doesn't translate directly to freeing the memory back to OS. It may free the memory, by calling free from C-library. But malloc also internally still may not be immediately release the memory to the OS.
@JoopEggen:So a process never shrinks to help OS?

t
the8472

The HotSpot JVM does 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.

In general shrinking ability and behavior depends on the chosen garbage collector, the JVM version since shrinking capability was often introduced in later versions long after the GC itself was added. Some collectors may also require additional options to be passed to opt into shrinking. And some most likely never will support it, e.g. EpsilonGC. So if heap shrinking is desired it should be tested for a particular JVM version and GC configuration.

JDK 8 and earlier

There are no explicit options for prompt memory reclamation in these versions but you can make the GC more aggressive in general by setting -XX:GCTimeRatio=19 -XX:MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=30 which will allow it to spend more CPU time on collecting and constrain the amount of allocated-but-unused heap memory after a GC cycle.

If you're using a concurrent collector you can also set -XX:InitiatingHeapOccupancyPercent=N with 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 generally is not a good idea, but on some types of machines with lots of spare CPU cores but short on memory it can make sense.

If you're using G1GC note that it only gained the ability to yield back unused chunks in the middle of the heap with jdk8u20, earlier versions were only able to return chunks at the end of the heap which put significant limits on how much could be reclaimed.

If you're using a collector with a default pause time goal (e.g. 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.

To verify that shrinking occurs or to diagnose why a GC decides not to shrink you can use GC Logging with -XX:+PrintAdaptiveSizePolicy may also provide insight, e.g. when the JVM tries to use more memory for the young generation to meet some goals.

JDK 9

Added the -XX:-ShrinkHeapInSteps option which can be be used to apply the shrinking caused by the options mentioned in the previous section more aggressively. Relevant OpenJDK bug.

For logging -XX:+PrintAdaptiveSizePolicy has been replaced with -Xlog:gc+ergo

JDK 12

Introduced the option to enable prompt memory release for G1GC via the G1PeriodicGCInterval (JEP 346), again at the expense of some additional CPU. The JEP also mentions similar features in Shenandoah and the OpenJ9 VM.

JDK 13

Adds similar behavior for ZGC, in this case it is enabled by default.


l
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.

Also see this related bug report


I think what you see from these java memory tools is memory freed within the Java process space. But this does not mean that the OS gets the memory back and can give it to another application
You can also see the total heap size, but if you don't trust Java tools, you can also use native, OS-level tools.
Correct me if I am wrong, but I can't really recall a case of a java process in e.g. the task manager ever shrinking. But I haven't really much experience in monitoring
I just verified to be sure, and I have seen it give back some memory! On Windows I like to use the vmmap app (it is a free download from Microsoft), it lets you see lots of interesting things about the memory usage of a process.
S
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.

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

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.


What if Xms and Xmx are set to the same value. Will the G1 still give back memory to the OS? (Pre JDK 12)
@StefanReich I do not think that this is correct, initalial heap and max heap could be set to the same values for example, while the app could consume a lot less.
@StefanReich 1) you have to tag me via @, otherwise I have no idea you replied 2) Xms is not minimum memory, but initial, as such you are wrong.
@Eugene awesome analysis! So it seems the problem lies more in the documentation of -Xms, now that more and more people (including the ones developing GCs) say it is the minimum heap value?
@Matthieu especially since there is InitialHeapSize already, making this even more confusing.
f
francesco foresti

this article here explains 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).


The OP is not update if heap has an upper limit but if the unused part of the heap is eventually reclaimed by OS to be used by other processes
I think what Francesco Foresti is saying is that some garbage collection settings will result in the heap shrinking and memory being given back to the OS, which I have seen in practice, also, see for instance: link
М
Макс Даниленко

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


Link-only answers are discouraged because links may break over time. Please extract relevant information from the post and add them to your answer, either as a quotation or in your own words.
@Genhis OTOH the links provided in this specific answer should be "quite" stable, since they point to JEPs on java.net.
ZGC was experimental in JDK 11. it is still experimental.