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.
Related
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.
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.
Does a thread self-delete and get garbage collected after it runs or does it continue to exist and consume memory even after the run() method is complete?
For example:
Class A{
public void somemethod()
{
while(true)
new ThreadClass().start();
}
public class ThreadClass extends Thread{
public ThreadClass()
{}
#Override
public void run() {......}
}
}
I want to clarify whether this thread will be automatically removed from memory, or does it need to be done explicitly.
This will happen automatically i.e. memory will be released automatically once the thread is done with its run method.
Threads only exist until the end of their run method, after that they are made eligible for garbage collection.
If you require a solution where memory is at a premium, you might want to consider an ExecutorService. This will handle the threads for you and allow you to concentrate on the logic rather than handling the threads and the memory.
Threads are automagically garbage collected on completion of the run method, hence you do not have to do it explicitly.
Threads will be garbage collected after their run method has completed. The notable exception to this is when you are using the android debugger. The android debugger will prevent garbage collection on objects that it is aware of, which includes threads that have finished running.
Why do threads leak on Android?
I've got a question about threads. When I do sth like this:
new Thread(new Runnable(){
#Override
public void run() {
//sth to do
}
}).start();
What happens when all the code in run() is executed ? Does the system automatically deletes the thread or does the thread still remain in memory?
thx & regards
When a thread finished its run() method, it will enter the 'dead' state. Then the next thread in your stack runs after.
Dead state :
"A thread is considered dead when its run() method completes. It may
still be a viable Thread object, but it is no longer a separate thread
of execution. Once a thread is dead, it can never be brought back to
life! (The whole "I see dead threads" thing.) If you invoke start() on
a dead Thread instance, you'll get a runtime (not compiler) exception.
And it probably doesn't take a rocket scientist to tell you that if a
thread is dead, it is no longer considered to be alive."
Java's Threading Model is a little bit more complicated than that.
Basically, a java.lang.Thread is just a wrapper around some data, not a process by itself. When you call the .start() method, a native thread is created and linked to your java Thread. This work is done by the JVM using internal data structures (JavaThread and OSThread).
Once the .run() method finish, many operations are performed by the JVM to delete the native thread that was used. Therefore, you won't see this thread anymore in you process list (using top or ps, for example).
However, the objects that were allocated in the heap and the java.lang.Thread instance itself stay in memory until a GC cycle collects them.
So, to sum up :
Yes, the JVM deletes the native thread that was used
No, the JVM does not delete the java.lang.Thread instance that was used
The GC will eventually collect this instance
For more information, you should read the book "Java Performance" by Charlie Hunt. It contains lots of information on this topic (and many others).
Hope that helps !
When the code in a thread finishes executing, the thread is stopped.
The Thread instance will still exist until it gets GC'd, but the actual system thread will no longer exist.
If you don't use any custom-configured thread pool mechanism, your thread will die and the Threadobject itself will be eligible to garbage collection.
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.