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

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.

Related

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.

garbage collector not working?

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.

Java "unstopped " executed/finished threads

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.

Java Multithreading: Behaviour when Reference count of thread object becomes zero

[Before I begin I tried searching related questions, since I found none, I ask a question here]
I am learning Java, and the following scenario hit my head:
class MyThread extends Thread {
void run(){
//a heavy function
}
}
And now in the main thread, I invoke this thread as:
public static void main(...){
new MyThread().start();
System.gc(); //just a request..
//end of main thread too.
//Reference to that MyThread object is now zero.
}
I ran that code. It seems the thread is still alive. The program ends when all the threads quit.
My questions:
When the reference count is zero, wont the thread be eligible for GC? If it is really eligible, what is the behaviour of garbage collection? Will the thread be terminated?
I know its a bad thing to do but is it well defined to not have otherThread.join() in main()?
I have a few explanation of myself (but I do not know how right I am -- the reason I made a post here):
JVM maitains a reference to the thread as long as it is active. So ref count is never really zero.
The executing function has an implicit this reference, so the ref count is again not zero.
Am I correct in any of the explanations above? Or is there any other explanation altogether?
Thanks and regards :)
Each running thread constitutes a root for the GC. Any object reachable from one of the roots is not eligible for GC, and the thread has a thread-local reference to the java.lang.Thread instance (returned by Thread.currentThread()). So no, your thread won't be GCed until it ends running, since the Thread instance is reachable from the running thread.
I don't see why it would be a bad thing not to call join() on the spawned thread. If you don't care when the spawned thread ends, you don't need to join it. The application will stop when the last non-daemon thread stops running.
Also, note that the number of references is not what is used by the GC to tell if an object is eligible for GC or not. Graphs of objects which maintain references to each other (a DOM tree for example) can be eligible for GC, if the graph is not reachable anymore.
1. JVM will terminate only when all the Non-Daemon thread including the Main thread has terminated. (Main thread not the main() method).
2. A Thread will die immediately as it has finished running its run() method, But as you will be knowing that, every thread (toe, ie thread of execution) is associated with the Instance of the Thread class.
3. So when the thread die, it moves in to the dead state (i am not mentioning the thread pool here) , But the object of Thread class which was associated with the thread is still there, but has permanently lost its threadness.
4. But there is a high chance that your thread is still running only the main method has finished.
5. Calling join() is not at all bad, but should be used with caution.
When the reference count is zero, wont the thread be eligible for GC?
No. A thread becomes eligible for GC when it terminates and there are no references.
If it is really eligible, what is the behaviour of garbage collection? Will the thread be terminated?
See above.
I know its a bad thing to do but is it well defined to not have otherThread.join() in main()?
It isn't a bad thing to do, and it is perfectly well-defined: the JVM will exit when all the non-daemon threads have exited.
JVM maitains a reference to the thread as long as it is active. So ref count is never really zero.
Correct.
The executing function has an implicit this reference, so the ref count is again not zero.
Incorrect. Consider static methods. The executing function is executing in an active thread, by definition, so the thread is active, by definition, so it can't be GC'd. Your thinking here is rather circular.

is there any way to confirm if the thread is killed at the end of execution?

is there any way to confirm if the thread is killed at the end of execution? If the garbage collector takes long time to destroy the threads even when they are available for GC, out of memory exceptions may arise. to get rid of those kind of issues, it would be good to know if the threads have been destroyed.
As of now, my understanding is that at the end of run method , the thread gets killed and we need not do anything explicitly to kill the thread instance.
Thanks in advance!
class A
{
public static void main()
{
Thread t = new Thread(new TestA());
t.start();
Thread t1 = new Thread(new TestB());
t1.start();
Thread t2 = new Thread(new TestC());
t2.start();
}
}
class TestA implements Runnable {
Thread t;
public void run() {
for(...){
try{
}catch()
{
....
}
}
}
}
You are absolutely right that "at the end of run method, the thread gets killed and we need not do anything explicitly to kill the thread instance". Simply letting the thread leave its run() method normally is enough.
If you want to make sure that a particular thread has terminated, then Thread.isAlive() will check, and Thread.join() will wait until it happens. If you have a particular set of threads that you're worried about, then keep a reference to them somewhere, and check up on them using these methods.
Thread.getAllStackTraces()
gets you a current map of threads/stacktraces. However I would normally expect the JVM to clear up the threads upon exit from run(). Obviously if you're using some sort of thread pooling then that's not the case.
You can use some softwares like visualvm to monitor the thread states .
These kind of softwares will give you full flexibility to profile your application in a visual way.
To check the state of a thread , you can call the getState() method on a thread object to see the state of the thread.
The javadoc of OutOfMemoryError says:
Thrown when the Java Virtual Machine cannot allocate an object because
it is out of memory, and no more memory could be made available by the
garbage collector.
So, if a thread is not running anymore and is eligible to GC, the GC will try to collect it before throwing an OOM. Like with any other object.
is there any way to confirm if the thread is killed at the end of execution?
There's no sense confirming something you know to be true. Whenever the JVM process dies, all its threads are automatically killed by the operating system. Any other behavior is a bug in the OS.
If the garbage collector takes long time to destroy the threads even when they are available for GC, out of memory exceptions may arise.
The garbage collector doesn't kill threads - the JVM wraps operating-system-specific thread libraries into a consistent Java-language thread abstraction, so those thread libraries determine when a thread dies.
my understanding is that at the end of run method, the thread gets killed and we need not do anything explicitly to kill the thread instance.
That is correct.
If you look up in the javadoc for the Thread class you will see many methods that might help you check what you want, for example:
activeCount() : Returns the number of active threads in the current thread's thread group.
You can use this as a debug method.
isAlive() : Tests if this thread is alive.
To check if a specific thread is alive.
join() : Waits for this thread to die.
If you call this at the end of your method then it will wait for the thread to join (i.e. to end execution) before advancing. If you call for all threads, then you are sure that all have finished when the main() has finished.
destroy() : Destroys this thread, without any cleanup.
Does what it says, but I would never suggest this.
Hope it helps!

Categories