This question is quite difficult if you try to work it out in your head. I suggest that you draw a diagram. You should represent the static variable p2 by a small box. Then draw other boxes representing the Phoenix objects as they are created. The explicit calls to finalize for these objects (both made by the main thread) cause p2 to be linked and unlinked with one of the two objects. You will see that you get a situation where one of the two Phoenix objects has no reference to it. So it becomes eligible for garbage collection. If during the "time consuming and memory intensive stuff" the Phoenix object is garbage collected, then the object's finalizer is going to be called (invoked) by the garbage collector thread (the JVM). The call to finalize causes the object to be relinked to p2, making the other Phoenix object eligible for garbage collection. So the fun goes on - but the problem has been answered already by this stage.
Here first P2 is referencing to new Phoenix object at line 1(as this is passed as argument to send in finalize() method) but as P2 is static in line 2 it starts referring to another Phoenix object and hence Phoenix object at line is eligible for garbage collection.
Now as the second statement says: //The JVM could have invoked the finalize() method at least once. I think its true. But as far as i think if the statement is like: //The JVM will invoke the finalize() method at least once. I think its not sure that finalize is called.
hope you got it.
(As far as i think, calling finalize() method at line 1 and 2 is done by compiler and not JVM, if I am wrong please guide me)
Joined: Aug 03, 2002
All threads are executing inside the JVM, so really the JVM calls (invokes) everything. What they should be using are the terms "main thread" and "garbage collection thread".
After line 1 nothing is eligible for gc because there's a static reference to that phoenix.
After line 2, the first phoenix is eligible for GC, because the static reference now points to the second phoenix. The first phoenix is dereferenced and thus eligible for GC. But does "is eligible for gc" really mean, that the object will be deleted?
The JVM could have invoked the finalize() method at least once.
I think, for one object, the garbage collector (which I think here is meant by JVM here) will call finalize once at most. Or not at all, isn't that true?
Assume finalize will be called once: If the GC calls finalize now for the first phoenix, it will give it a reference again. Now it's no longer eligible, but on the first phoenix, finalize will never be called again. As phoenix #2 now is eligible, GC calls its finalize() and so gives it a reference again, leaving phoenix #1 alone in the dark (dereferenced) again. Phoenix one is eligible, but finalize has already been invoked, so it will not be called again. And the first phoenix will be deleted.
I think whether or not the GC call the objects' finalize(), one of the two will be garbage collected, one will survive. But you cannot tell which one cause you do not know, if the GC will call finalize() or not.
One more question: do you really believe that such a tricky question will be on the exam?
I'm confused by why the answer "JVM could have invoked the finalize() method at least twice" isn't also correct. Here's my understanding of what will happen.
We have three Phoenix objects, call them A, B and C. We have two reference variables, p2 and p3.
Phoenix C is safe from garbage collection because it has p3 pointing to it. At the time we first hit the memory intensive stuff, B is safe because it is referenced by p2, and A is eligible for garbage collection. When (if) garbage collection happens, the JVM will invoke finalize() on A (because it has not yet invoked finalize() as part of garbage collection, even though the code has called the method programmatically). When that happens, p2 will be changed to refer to A, which makes A safe and makes B eligible for garbage collection. So if there's a second pass of garbage collection after more memory intensive stuff, then this time through B will get finalize() called on it, letting it rise from the ashes but making A eligible for garbage collection again. If a third garbage collection runs, then A has had it - it's already had its only free life through having its finalize() method run, so it gets collected.
So, by my reckoning, the JVM could invoke finalize() twice but not more than twice on the three Phoenix objects in the question. [ October 24, 2006: Message edited by: Dave McIntyre ]
Originally posted by Dave McIntyre: I'm confused by why the answer "JVM could have invoked the finalize() method at least twice" isn't also correct...So, by my reckoning, the JVM could invoke finalize() twice but not more than twice on the three Phoenix objects in the question.
Yeah, I just did this question and came to the same conclusion, and I think the Master Exam answer is incorrect. You can (probably) demonstrate this by replacing "do time consuming and memory intensive stuff" with:
and adding a System.out.println("finalize()"); to the finalize() method. It showed four invocations of finalize() when I ran it.