简体   繁体   中英

Delaying System.gc() in Java

As far as I understand the documentation of System.gc() this call will point the GC towards regions of memory that the caller was 'working' on. There's no guarantee for any clean up whatsoever happening after the method returns.

But say there was now obsolet data and the GC 'decided' to free the memory used by that data. Does this mean the freeing happened before the method returns? And if yes, is there a way to delay the freeing of memory itself? Would it make sense?

Say the statement above is true; I am aware that simply delegating the call of System.gc() to another thread would make no sense following the logic implied by the documentation. Would it on the other hand make sense to delegate references of obsolet data to another thread while simultaneously voiding the previous references anywhere else and then calling the GC on that thread?

For instance; say a singleton thread instance acts as a consumer and it simply consumes objects.

public static void consumeForGC(Object… args)

The objects are passed by reference which should (must?.) hinder the GC from freeing their allocated memory space. So when now calling the GC in the scope of this consumeForGC(…) in which the last known references to the given arguments are, does this achieve similar behavior to simply calling it (preferably at the end) of a caller and waiting for the call to return? Besides being very hacky, it would probably only increase the chances for some allocations to be released sooner, but at least it could give some control over which those are. The rest of the program could also carry on because it doesn't have to wait for the GC to finish whatever it will actually do.

I hope this question is not too irrelevant n.netheless I am curious to hear what you guys think about this

As far as I understand the documentation of System.gc() this call will point the GC towards regions of memory that the caller was 'working' on.

It does not really "point towards memory". Rather invoking System.gc() can trigger a GC cycle that will run with somewhat different parameters compared to those automatically triggered by memory pressure or (in some concurrent collectors) background timers.

A GC cycle is always application-global, cleaning up some or all of the objects that are deemed unreachable from GC roots.

As a rule of thumb one shouldn't trigger System.gc without analysis of GC logs and application profiling to identify whether doing so improves some metrics. Used incorrectly it'll lead to excessive CPU consumption, decreased throughput and increased latency.

There's no guarantee for any clean up whatsoever happening after the method returns.

The specification is vague, in practice it depends on the JVM, selected garbage collector and config flags. Eg on hotspot there are flags DisableExplicitGC , ExplicitGCInvokesConcurrent and several other flags controlling its behavior.

But changing these parameters can impact other parts of the system, eg direct ByteBuffer allocations can resort to calling System.gc to trigger reclamation of unused buffers. If manual GCing is disabled or insufficiently aggressive it could lead to OOMEs when allocating direct buffers.

Does this mean the freeing happened before the method returns? And if yes, is there a way to delay the freeing of memory itself? Would it make sense?

It does not promise to clean any specific objects, or any objects at all for the matter. But if it does trigger a GC then it'll only return once that cycle is complete, but that does not guarantee that all unreachable objects have been collected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM