I know that garbage collection is automated in Java. But I understood that if you write System.gc()
in your code the Java VM may or may not decide at runtime to do a garbage collection at that point. How does this work precisely? On what basis/parameters exactly does the VM decide to do (or not do) a GC when it sees a System.gc()
? Are there maybe examples in which case it is a good idea to put this in your code?
相关问题
- Delete Messages from a Topic in Apache Kafka
- Jackson Deserialization not calling deserialize on
- How to maintain order of key-value in DataFrame sa
- StackExchange API - Deserialize Date in JSON Respo
- Difference between Types.INTEGER and Types.NULL in
Accroding to Thinking in Java by Bruce Eckel, one use case for explicit System.gc() call is when you want to force finalization, i.e. the call to finalize method.
There is a LOT to be said in taking the time to test out the various garbage collection settings, but as was mentioned above it usually not useful to do so.
I am currently working on a project involving a memory-limited environment and a relatively large amounts of data--there are a few large pieces of data that push my environment to its limit, and even though I was able to bring memory usage down so that in theory it should work just fine, I would still get heap space errors---the verbose GC options showed me that it was trying to garbage collect, but to no avail. In the debugger, I could perform System.gc() and sure enough there would be "plenty" of memory available...not a lot of extra, but enough.
Consequently, The only time my application calls System.gc() is when it is about to enter the segment of code where large buffers necessary for processing the data will be allocated, and a test on the free memory available indicates that I'm not guaranteed to have it. In particular, I'm looking at a 1gb environment where at least 300mb is occupied by static data, with the bulk of the non-static data being execution-related except when the data being processed happens to be at least 100-200 MB at the source. It's all part of an automatic data conversion process, so the data all exists for relatively short periods of time in the long run.
Unfortunately, while information about the various options for tuning the garbage collector is available, it seems largely an experimental process and the lower level specifics needed to understand how to handle these specific situations are not easily obtained.
All of that being said, even though I am using System.gc(), I still continued to tune using command line parameters and managed to improve the overall processing time of my application by a relatively significant amount, despite being unable to get over the stumbling block posed by working with the larger blocks of data. That being said, System.gc() is a tool....a very unreliable tool, and if you are not careful with how you use it, you will wish that it didn't work more often than not.
If you use direct memory buffers, the JVM doesn't run the GC for you even if you are running low on direct memory.
If you call
ByteBuffer.allocateDirect()
and you get an OutOfMemoryError you can find this call is fine after triggering a GC manually.while system.gc works,it will stop the world:all respones are stopped so garbage collector can scan every object to check if it is needed deleted. if the application is a web project, all request are stopped until gc finishes,and this will cause your web project can not work in a monent.
The Java Language Specification does not guarantee that the JVM will start a GC when you call
System.gc()
. This is the reason of this "may or may not decide to do a GC at that point".Now, if you look at OpenJDK source code, which is the backbone of Oracle JVM, you will see that a call to
System.gc()
does start a GC cycle. If you use another JVM, such as J9, you have to check their documentation to find out the answer. For instance, Azul's JVM has a garbage collector that runs continuously, so a call toSystem.gc()
won't do anythingSome other answer mention starting a GC in JConsole or VisualVM. Basically, these tools make a remote call to
System.gc()
.Usually, you don't want to start a garbage collection cycle from your code, as it messes up with the semantics of your application. Your application does some business stuff, the JVM takes care of memory management. You should keep those concerns separated (don't make your application do some memory management, focus on business).
However, there are few cases where a call to
System.gc()
might be understandable. Consider, for example, microbenchmarks. No-one wants to have a GC cycle to happen in the middle of a microbenchmark. So you may trigger a GC cycle between each measurement to make sure every measurement starts with an empty heap.In short:
Parameters is VM dependent.
Example usage- can't think of one for runtime/production apps, but it is useful to run it for some profiling harnesses, like calling