garbage collector not working? - java

my JDK version is 1.7.0_25
class A {
public void finalize() {
System.out.println("deleting...");
}
}
public class Test {
public static void main(String[] args) {
new A();
System.gc();
System.out.println("main class");
}
}
i expected the out put as
deleting...
main class
but in my case there were no output what is the reason ? and when i compile and run the code online with JDK 1.7.0_09 then the outputs are ,
main class
deleting...
why the "main class" prints first ?

The GC never guarantees when the the clean up happens,
finalize()
may be or may not be called.
By doin System.gc(); you are only requesting the GC to be invoked but its up to the JVM to fulfill your request.
Will the System.gc() invoke the cleanup?
The answer varies depending on lots of factors, like which JVM you're running on, which mode it's in, and which garbage collection algorithm it's using.
I wouldn't depend on it in your code. If the JVM is about to throw an OutOfMemoryError, calling System.gc() won't stop it, because the garbage collector will attempt to free as much as it can before it goes to that extreme.
So... if there is anything that you would want to perform for certain, do not write that code in finalize()

There is no guarantee whether finalize() method will be called or not when you call System.gc() method. Go throgh java API. And for the second question , main() method is a thread. And when you call garbage collector , it will be executed in another thread.So if you understand threads , by now you will know the answer (You can't predict thread execution order)

It is not specified when finalization will happen. The only thing that is specified / guaranteed is that finalization will happen before a finalizable object is actually deleted from the heap.
In practice, finalization is typically done by a special finalization thread that gets notified when the main GC thread finishes its work. It looks like control is returning to the main thread before the finalization thread gets to process the object.
Basically, you cannot rely on the order in which these things happen. And that is one of the reasons why depending on finalization to do things is generally a bad idea.
And besides, it is not even guaranteed that the System.gc() call will do anything.
In short, what you are observing is "within the envelope" of specified behaviour for finalization. The garbage collector is working. It is your expectations that are incorrect.

The other answers corrrectly stated that there is no way to make sure finalizers are run. I just wnated to add something concerning the question about the execution-order:
When a GC detects an object with a finalize()-method is to be deleted it doesn't delete it right away but first puts it on the finalization-queue. After that GC is finished and the application resumes working the VM will start running all queued finalizers - that should explain the order of your output. Only after that can the object actually be GCed.

Related

What Runtime gc actually does and what is causing this output?

Does it forces thread scheduler to pick up gc thread for execution or it simply plays with priority of gc thread?
class Test1
{
public static void main(String[] args)
{
Test1 test = new Test1();
test = null;
Runtime.getRuntime().gc();
System.out.println("in main after gc...");
public void finalize()
{
System.out.println("in finalize method...");
}
}
Output possibility 1:
in finalize method...
in main after gc...
Output possibility 2:
in main after gc...
in finalize method...
Output possibility 1: explanation:
This output is possibly caused because "Runtime.getRuntime().gc()" made gc thread to execute which printed first line after which main thread was picked up and printed the second line.
Output possibility 2: explanation:
What is causing this output?
Is it because "Runtime.getRuntime().gc()" made priority of gc thread high so that main thread continued for some time after which gc thread was picked up?
What does Runtime.gc() actually do?
In theory it could do a variety of things. For example:
It may cause the garbage collector to run NOW, pausing the current thread until it has completed.
It may do absolutely nothing.
It may do something else; e.g. trigger a GC at the opportunity, or increase the priority of the GC threads.
There is sufficient (deliberate) ambiguity in spec that it is not possible to say whether a gc() call will cause a particular object to be collected. Certainly, not for all of the ways / all of the platforms where you could run the application.
You seem to be interested / concerned with the timing of the finalize. The "bad news" is that even if you know that a particular gc() is going to find that a given object is unreachable, you the cannot be sure that it will be finalized before the gc() call completes.
In fact, when a typical HotSpot GC finds an unreachable object that is finalizable, it enqueues it to be finalized AFTER the GC cycle. The object won't be deleted yet.
Therefore, the actual output from the above could be any of the following:
One message:
in main after gc
Two messages:
in main after gc
in finalize method
Two messages in the other order
in finalize method
in main after gc
Case one will occur if either the gc() call is ignored, or if the JVM exits before the JVM processes the finalization queue.
Case two is the most likely behavior for current generation JVMs.
Case three could occur if the something else triggers a GC before this gc() call happens. It could also occur in a (hypothetical) Java implementation where finalization happens synchronously with the garbage collection.

How does gc method work?

public class GarbageC {
public void finalize()
{
System.out.println("Finalize method");
}
public static void main(String[] args) {
GarbageC c1=new GarbageC();
GarbageC c2=new GarbageC();
c1=null;
c2=null;
System.gc();
System.out.println("abc");
}
}
While I'm debugging this code, the o/p is coming as
Finalize method
Finalize method
abc
and when I run, I get this
abc
Finalize method
Finalize method
Why am I getting different outputs in both the cases
Calling System.gc() is a request. The runtime doesn't have to do collect garbage in response. It may full well decide to ignore you. As such, you can't depend on it doing the same thing consistently.
Chances are, in debug mode it really does cause a garbage collection to be run. In non-debug mode it either just doesn't collect the garbage or waits until an opportune moment to do so.
If you run it often enough you could get any of the 3 possible outputs.
The garbage collection process possibly runs in a dedicated thread (at least in any recent VM it will), so the output depends on the speed of each thread (your main thread and the GC thread of the VM).
In debug mode, the main thread is significantly slower (you may pause it indefinetly when stepping through the code). Thus the GC overtakes your main thread. When you simply run the program; the main thread will most likely run through to completeion before the VM even attempts to garbage collect.
A call to System.gc() is only a request "hey please do a gc", even if the VM honors it (its not required to), your request will be passed to the GC thread; that involves at least a slight delay before the GC will actually begin work; and some more time until it actually discovers your garbage objects and then finally collects them.

Why does Java ThreadPoolExecutor override finalize()

I'd like to know why the ThreadPoolExecutor finalize() method invokes its shutdown() method when it is known that the finalize method only gets invoked by the GC AFTER all of its threads have been stopped. So why does ThreadPoolExecutor override finalize() at all?
It seems misleading to me (and a source of a thread-leak my project) that ThreadPoolExecutor.finalize() invokes shutdown() as this gives the strong (but false) impression that
- ThreadPoolExecutor manages the lifecycle of its threads and will stop the threads when the GC collects the ThreadPoolExecutor object
- it is only necessary to invoke shutdown() or shutdownNow() if you want deterministic results as opposed to relying on the GC to tidy up (obviously, poor practice to do this!)
Notes
In this thread, why-doesnt-this-thread-pool-get-garbage-collected Affe explains why it is still necessary for the client to invoke shutdown()
In this thread, why-threadpoolexecutor-finalize-invokes-shutdown-and-not-shutdownnow the originator is puzzled by this topic but the answers aren't as comprehensive as in 1
The JavaDocs for ThreadPoolEecutor.finalize() do include the words "and it has no threads" but this is easily overlooked.
First, if you think this is a bug, then report it to Oracle.
Second, we cannot definitely answer your question, because you are essentially asking "why did they design it this way" ... and we weren't there when they made the decision.
But I suspect the reason is that the current choice was deemed to be the lesser of two evils:
On the one hand, if you a threadpool could be shutdown merely because it was no longer directly referenced, then threads that are doing real work could be terminated prematurely.
On the other hand, as you observed a threadpool that doesn't get automatically shutdown on becoming on longer directly reachable could be a memory leak.
Given that there are clearly ways to avoid the storage leak, I think that the 2nd alternative (i.e. the current behaviour) is the lesser of the evils.
Anyway, there is a clear evidence that this behaviour was considered by the designers; i.e. this quotation from the ThreadPoolExecutor javadoc:
Finalization
A pool that is no longer referenced in a program AND has no remaining threads will be shutdown automatically. If you would like to ensure that unreferenced pools are reclaimed even if users forget to call shutdown(), then you must arrange that unused threads eventually die, by setting appropriate keep-alive times, using a lower bound of zero core threads and/or setting allowCoreThreadTimeOut(boolean).
(And that sort of answer's #fge's comment. It happens when inactive worker threads are configured to time out.)
I also think there is an implementation-based reason as well. Take a look at the code here.
Each thread in the thread pool has a reference to a Runnable, which is actually an instance of the inner class ThreadPoolExecutor.Worker. This means that there is a strong reference path from the (live, though probably idle) Thread to the ThreadPoolExecutor.Worker object, and from that object to the enclosing ThreadPoolExecutor instance. And since live threads are always reachable, a ThreadPoolExecutor instance is remains reachable until all of its threads actually terminate.
Now I/we can't tell you which came first, the behaviour or the javadoc specification. See my "Secondly ..." point above ...
But, like I said above ("Firstly ..."), if you think this is a bug, report it to Oracle. And the same goes if you think that the javadoc is misleading ... though I think your argument there is weak given the material that I quoted.
As to why they overloaded finalize() to call shutdown() if shutdown() does nothing in this circumstance:
it may have done something significant in earlier versions, and
the shutdown() method ends by calling a hook method that is apparently overridden in subclasses to do something significant ... according to the comments.

can i logically control finalize() method to run or not in java

Can I logically control finalize() method to run or not in java ?
I want to run finalize() method depending on the result returned from a conditional method.
Can I logically control finalize() method to run or not in java ?
Answer is you cannot.
I want to run finalize() method depending on the result returned from
a conditional method.
You can use the condition or a flag check in your finalize to decide whether you want to do the cleanup or not.
No you cannot. Calls Asynchronously when GC started cleanup.
See docs on same,
Called by the garbage collector on an object when garbage collection determines that there are no more references to the object. A subclass overrides the finalize method to dispose of system resources or to perform other cleanup.
But doing cleanup(or some logic) in the finalize seems little design flaw to me.
Did u try
Runtime.getRuntime().runFinalizersOnExit(boolean value)
Frankly you can't control finalize method. It all depends upon JVM logic.
At the most you can only call System.gc(); to request JVM to run Garbage Collector but again it will purely depend upon JVM algorithm whether to run it or not.
Finalize method is just an option to do some manipulations if your object is going to be garbage collected at any point of time but not guaranteed.
if you really want to do custom tasks you can override finalize method. But it is best not to rely on it.

Will setting the only reference to null mean it and its child threads are garbage collected?

I have an application which has to live as a service, I create an object which then spawns off a buch of threads.
If I set the only reference to that object to null will all the child threads get cleaned up? or will I suffer from a memory leak.
Do I have to explicitly terminate all the child threads?
Threads and static references are 'root objects'. They are immune from GCing and anything that can be traced back to them directly or indirectly cannot be collected. Threads will therefore not be collected as long as they are running. Once the run method exits though, the GC can eat up any unreferenced thread objects.
Yes, you need to make sure your other threads stop. The garbage collector is irrelevant to this. You should also do so in an orderly fashion though - don't just abort them.
Here's a pattern in C# for terminating threads co-operatively - it's easy to translate to Java.
As others have mentioned, threads won't be cleaned up until they've been stopped. They are root objects for the GC, so you don't have to keep references to them. Your application won't quit until all threads have exited.
There is one exception to this rule. If you mark a thread as a daemon then it will not prevent your application from exiting, and if there are no other non-daemon threads running they it will be cleaned up automatically.
See the javadoc for Thread for more info.
No matter the theory (or StackOverflow answers), you should also create some test to see if what you intended to do, is really happening. Maybe you have some forgotten pointer preventing garbage collection.

Categories