Java garbage collector execution - java

Finalize methods are invoked by the garbage collector prior to reclaiming the memory occupied by the object, which has the finalize() method. This means you do not know when the objects are going to be finalized.
Why we dont know when garbage collector will run. Does the founders of Java also dont know this. There will be a specific condition or time (for sure) when garbage collector will run.

Why we dont know when garbage collector will run.
It is a deliberate design choice. This gives the JVM the flexibility to do garbage collection at a time (and in a way) that gives optimal performance, or minimal pauses ... depending on the collector that the user has chosen.
There will be a specific condition or time (for sure) when garbage collector will run.
No.
The only thing that it is pretty much guaranteed is that a full GC will be run before the JVM decides to "give up" and throw an OutOfMemoryError.
There is a System.gc() method that you can call to suggest to the JVM that it should run a garbage collection. However:
The JVM is allowed to ignore the suggestion.
If the JVM pays attention to the suggestion, your application is liable to perform worse than if you just let the JVM decide. Calling System.gc() in production code is nearly always a BAD IDEA.
The bottom line is that if you want to guarantee that a certain action happens, you should not implement that action using a finaliser.

When the garbage collection is done is down to the implementation but it will usually happen when the free memory has reached below a certain threshold.
I remember hearing that it is allowed for an implementation to have no garbage collection at all!
You will not be able to tell for sure when the collection will happen without knowing the implementation details and then monitoring whatever it is that the GC is monitoring. But even this will have problems and it is highly discouraged as it completely defeats the portability of Java.
The is a method System.gc which:
suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.
However use of this is also discouraged.

Related

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 nonetheless 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. E.g. 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, e.g. 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.

Is it good pratice to call System.gc() in all user defined methods

Is it a good practice to call System.gc() in all my Java methods?
Example: I have a class. Before the return statement of all the functions, i am trying to call the System.gc() function. Is it correct?
No. There is barely ever a need to call System.gc(), since garbage collection is automatic and the JVM knows what it's doing.
As manouti said, the method is simply a suggestion. At one time it was possible to "force" GC to run if you called System.gc() several times in succession, but all in all it's not your job to worry about the garbage collector.
If you need to affect how the GC works, you can do that by providing command line arguments to select different collection algorithms and tune the parameters as explained here.
Calling System.gc() from application code is a bad idea1. Calling it frequently is a TERRIBLE idea.
Running the GC is a relatively expensive operation, especially if it runs when it is not necessary to run it. And an application rarely has the information available to it to know when it is necessary.
The Java runtime has a much better handle on when and how to run the garbage collector efficiently. Leave it to make that decision for itself.
Reference:
Why is it bad practice to call System.gc()?
Example: I have a class. Before the return statement of all the functions, i am trying to call the System.gc() function. Is it correct?
Absolutely not.
1 - There are one or two edge cases where calling System.gc() is justifiable in production code. However, these are a tiny exception.
It does not really matter of you call or do not call System.gc().
It is not guaranteed that the GC will kick in and it would most likely not run as the JVM is much smarter to determine where to run GC than a developer.
Is it a good practice to call System.gc() in all my Java methods?
You don't at all need to call System.gc() in your program. It's not a good practice. Even if you do that, it's not certain that jvm will run the garbage collector on your command.
Just try to avoid creating unnecessary objects in your class. Deference them if you don't need it. Check here How garbage collector works in Java.
Ensure that there are no memory leaks in your code.
Is there any need to call System.gc() explicitly..? If yes, where can
i call..?
system-gc-invocation-a-suitable-scenario
No, it's not good practice, at least not in all methods. It may even cause performance overhead if the number of method calls is huge and more time gets allocated for GC (and depending on the type of the GC).
Furthermore, the behavior of System.gc() is not predictable as implied by the docs:
Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.

Forcing Java virtual machine to run garbage collector [duplicate]

This question already has answers here:
How to force garbage collection in Java?
(25 answers)
Closed 8 years ago.
I have a complex java application running on a large dataset. The application performs reasonably fast but as time goes it seems to eat lots of memory and slow down. Is there a way to run the JVM garbage collector without re-starting the application?
No, You cant force garbage collection.
Even using
System.gc();
You can just make a request for garbage collection but it depends on JVM to do it or not.
Also Garbage collector are smart enough to collect unused memory when required so instead of forcing garbage collection you should check if you are handling objects in a wrong way.
If you are handling objects in a wrong way (like keeping reference to unnecessary objects) there is hardly anything JVM can do to free the memory.
From Doc
Calling the gc method suggests that the Java Virtual Machine expend
effort toward recycling unused objects in order to make the memory
they currently occupy available for quick reuse. When control returns
from the method call, the Java Virtual Machine has made a best effort
to reclaim space from all discarded objects.
Open Bug regarding System.gc() documentation
The documentation for System.gc() is extremely misleading and fails to
make reference to the recommended practise of never calling
System.gc().
The choice of language leaves it unclear what the behaviour would be
when System.gc() is called and what external factors will influence
the behaviour.
Few useful link to visit when you think you should force JVM to free up some memory
1. How does garbage collection work
2. When does System.gc() do anything
3. Why is it bad practice to call System.gc()?
All says
1. You dont have control over GC in Java even System.gc() dont guarantee it.
2. Also its bad practise as forcing it may have adverse effect on performance.
3. Revisit your design and let JVM do his work :)
you should not relay on System.gc() - if you feel like you need to force GC to run it usually means that there is something wrong with your code/design. GC will run and clear your unused objects if they are ready to be created - please verify your design and think more about memory management, look as well for loops in object references.
The
System.gc()
call in java, suggest to the vm to run garbage collection. Though it doesn't guarantee that it will actually do it. Nevertheless the best solution you have. As mentioned in other responses jvisualvm utility (present in JDK since JDK 6 update 7), provides a garbage functionality as well.
EDIT:
your question open my appetite for the topic and I came across this resource:
oracle gc resource
The application performs reasonably fast but as time goes it seems to eat lots of memory and slow down.
These are a classic symptoms of a Java memory. It is likely that somewhere in your application there is a data structure that just keeps growing. As the heap gets close to full, the JVM spends an increasing proportion of its time running the GC in a (futile) attempt to claw back some space.
Forcing the GC won't fix this, because the GC can't collect the data structure. In fact forcing the GC to run just makes the application slower.
The cure for the problem is to find what is causing the memory leak, and fix it.
Performance gain/drop depends how often you need garbage collection and how much memory your jvm has and how much your program needs.
There is no certainity(its just a hint to the interpreter) of garbage collection when you call System.gc() but at least has a probability. With enough number of calls, you can achieve some statistically derived performance multiplier for only your system setup.
Below graph shows an example program's executions' consumptions and jvm was given only 1GB(no gc),1GB(gc),3GB(gc),3GB(no gc) heaps respectively to each trials.
At first, when jvm was given only 1GB memory while program needed 3.75GB, it took more than 50 seconds for the producer thread pool to complete their job because having less garbage management lead to poor object creation rate.
Second example is about %40 faster because System.gc() is called between each production of 150MB object data.
At third example, jvm is given 3GB memory space while keeping System.gc() on. More memory has given more performance as expected.
But when I turned System.gc() off at the same 3GB environment, it was faster!
Even if we cannot force it, we can have some percentage gain or drain of performance trying System.g() if we try long enough. At least on my windows-7 64 bit operating system with latest jvm .
Garbage collector runs automatically. You can't force the garbage collector.
I do not suggest that you do that but to force the garbage collector to run from within your java code you can just use all the available memory, this works because the garbage collector will run before the JVM throws OutOfMemoryError...
try {
List<Object> tempList = new ArrayList<Object>();
while (true) {
tempList.add(new byte[Integer.MAX_VALUE]);
}
} catch (OutOfMemoryError OME) {
// OK, Garbage Collector will have run now...
}
My answer is going to be different than the others but it will lead to the same point.
Explain:
YES it is possible to force the garbage collector with two methods used at the same time and in the same order this are:
System.gc ();
System.runFinalization ();
this two methods call will force the garbage collector to execute the finalise() method of any unreachable object and free the memory. however the performance of the software will down considerable this is because garbage runs in his own thread and to that one is not way to controlled and depending of the algorithm used by the garbage collector could lead to a unnecessary over processing, It is better if you check your code because it must be broken to you need use the garbage collector to work in a good manner.
NOTE: just to keep on mind this will works only if in the finalize method is not a reassignment of the object, if this happens the object will keep alive an it will have a resurrection which is technically possible.

What conditions would prevent the JVM from running a FULL Garbage Collection?

What conditions would prevent the JVM from running a FULL Garbage Collection when the CPU is at 5% to 8% load?
I am seeing a constant shallow GC cycle, but not able to tune the JVM to want to run FULL GC.
Where can I go to find the conditions that the JVM says "I am too busy to run".
When I was studying for my SCJP certification a lot of emphasis was made on
"You can not do anything to force the
GC to run at any given time, you can
just give hints to it"
The whole idea of having an automatic GC is precisely not having to worry about how or when it runs to clean up free memory for you. So, there is no way to actually change when or how GC does actually run... you would have to re-implement one JVM to do what you want.
There are just so many factors involved in this, there may be other, more elegant solutions for this.
It depends entirely on the garbage collector algorithm that you're using in your particular JDK. About all you can guarantee about garbage collection is that if the JVM throws an OutOfMemoryError, the garbage collector made its best effort to collect every unreachable/weakly reachable object. Even System.gc() doesn't guarantee anything, a no-op is a completely legal implementation.
Hence in that light I don't know if your question has any weight. If you truly believe that you need to tweak the garbage collector, it would help if you posted the problems you're seeing, and the profiling data that leads to believe that poor GC performance is the problem.
Outside of this, the garbage collector should be treated like a black box. The logic behind its implementation is surprisingly complex, and there's a very good chance it knows better than you what it ought to be doing at any given time. 99 times out of 100, trying to force the garbage collector to behave in a particular way will lower performance, not increase it.
It's not that it's to busy to run, but it does simply not need extra memory.

Why do you not explicitly call finalize() or start the garbage collector?

After reading this question, I was reminded of when I was taught Java and told never to call finalize() or run the garbage collector because "it's a big black box that you never need to worry about". Can someone boil the reasoning for this down to a few sentences? I'm sure I could read a technical report from Sun on this matter, but I think a nice, short, simple answer would satisfy my curiosity.
The short answer: Java garbage collection is a very finely tuned tool. System.gc() is a sledge-hammer.
Java's heap is divided into different generations, each of which is collected using a different strategy. If you attach a profiler to a healthy app, you'll see that it very rarely has to run the most expensive kinds of collections because most objects are caught by the faster copying collector in the young generation.
Calling System.gc() directly, while technically not guaranteed to do anything, in practice will trigger an expensive, stop-the-world full heap collection. This is almost always the wrong thing to do. You think you're saving resources, but you're actually wasting them for no good reason, forcing Java to recheck all your live objects “just in case”.
If you are having problems with GC pauses during critical moments, you're better off configuring the JVM to use the concurrent mark/sweep collector, which was designed specifically to minimise time spent paused, than trying to take a sledgehammer to the problem and just breaking it further.
The Sun document you were thinking of is here: Java SE 6 HotSpot™ Virtual Machine Garbage Collection Tuning
(Another thing you might not know: implementing a finalize() method on your object makes garbage collection slower. Firstly, it will take two GC runs to collect the object: one to run finalize() and the next to ensure that the object wasn't resurrected during finalization. Secondly, objects with finalize() methods have to be treated as special cases by the GC because they have to be collected individually, they can't just be thrown away in bulk.)
Don't bother with finalizers.
Switch to incremental garbage collection.
If you want to help the garbage collector, null off references to objects you no longer need. Less path to follow= more explicitly garbage.
Don't forget that (non-static) inner class instances keep references to their parent class instance. So an inner class thread keeps a lot more baggage than you might expect.
In a very related vein, if you're using serialization, and you've serialized temporary objects, you're going to need to clear the serialization caches, by calling ObjectOutputStream.reset() or your process will leak memory and eventually die.
Downside is that non-transient objects are going to get re-serialized.
Serializing temporary result objects can be a bit more messy than you might think!
Consider using soft references. If you don't know what soft references are, have a read of the javadoc for java.lang.ref.SoftReference
Steer clear of Phantom references and Weak references unless you really get excitable.
Finally, if you really can't tolerate the GC use Realtime Java.
No, I'm not joking.
The reference implementation is free to download and Peter Dibbles book from SUN is really good reading.
As far as finalizers go:
They are virtually useless. They aren't guaranteed to be called in a timely fashion, or indeed, at all (if the GC never runs, neither will any finalizers). This means you generally shouldn't rely on them.
Finalizers are not guaranteed to be idempotent. The garbage collector takes great care to guarantee that it will never call finalize() more than once on the same object. With well-written objects, it won't matter, but with poorly written objects, calling finalize multiple times can cause problems (e.g. double release of a native resource ... crash).
Every object that has a finalize() method should also provide a close() (or similar) method. This is the function you should be calling. e.g., FileInputStream.close(). There's no reason to be calling finalize() when you have a more appropriate method that is intended to be called by you.
Assuming finalizers are similar to their .NET namesake then you only really need to call these when you have resources such as file handles that can leak. Most of the time your objects don't have these references so they don't need to be called.
It's bad to try to collect the garbage because it's not really your garbage. You have told the VM to allocate some memory when you created objects, and the garbage collector is hiding information about those objects. Internally the GC is performing optimisations on the memory allocations it makes. When you manually try to collect the garbage you have no knowledge about what the GC wants to hold onto and get rid of, you are just forcing it's hand. As a result you mess up internal calculations.
If you knew more about what the GC was holding internally then you might be able to make more informed decisions, but then you've missed the benefits of GC.
The real problem with closing OS handles in finalize is that the finalize are executed in no guaranteed order. But if you have handles to the things that block (think e.g. sockets) potentially your code can get into deadlock situation (not trivial at all).
So I'm for explicitly closing handles in a predictable orderly manner. Basically code for dealing with resources should follow the pattern:
SomeStream s = null;
...
try{
s = openStream();
....
s.io();
...
} finally {
if (s != null) {
s.close();
s = null;
}
}
It gets even more complicated if you write your own classes that work via JNI and open handles. You need to make sure handles are closed (released) and that it will happen only once. Frequently overlooked OS handle in Desktop J2SE is Graphics[2D]. Even BufferedImage.getGrpahics() can potentially return you the handle that points into a video driver (actually holding the resource on GPU). If you won't release it yourself and leave it garbage collector to do the work - you may find strange OutOfMemory and alike situation when you ran out of video card mapped bitmaps but still have plenty of memory. In my experience it happens rather frequently in tight loops working with graphics objects (extracting thumbnails, scaling, sharpening you name it).
Basically GC does not take care of programmers responsibility of correct resource management. It only takes care of memory and nothing else. The Stream.finalize calling close() IMHO would be better implemented throwing exception new RuntimeError("garbage collecting the stream that is still open"). It will save hours and days of debugging and cleaning code after the sloppy amateurs left the ends lose.
Happy coding.
Peace.
The GC does a lot of optimization on when to properly finalize things.
So unless you're familiar with how the GC actually works and how it tags generations, manually calling finalize or start GC'ing will probably hurt performance than help.
Avoid finalizers. There is no guarantee that they will be called in a timely fashion. It could take quite a long time before the Memory Management system (i.e., the garbage collector) decides to collect an object with a finalizer.
Many people use finalizers to do things like close socket connections or delete temporary files. By doing so you make your application behaviour unpredictable and tied to when the JVM is going to GC your object. This can lead to "out of memory" scenarios, not due to the Java Heap being exhausted, but rather due to the system running out of handles for a particular resource.
One other thing to keep in mind is that introducing the calls to System.gc() or such hammers may show good results in your environment, but they won't necessarily translate to other systems. Not everyone runs the same JVM, there are many, SUN, IBM J9, BEA JRockit, Harmony, OpenJDK, etc... This JVM all conform to the JCK (those that have been officially tested that is), but have a lot of freedom when it comes to making things fast. GC is one of those areas that everyone invests in heavily. Using a hammer will often times destroy that effort.

Categories

Resources