This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
"Phantom reference objects, which are enqueued after the collector determines that their referents may otherwise be reclaimed. Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism."
1>when to claim it's a Phantom Reference or Weak Reference or Soft Reference?
2>Please Explain a bit on Phantom Reference,i'm not getting it !!
Okay, let's give an example of what happens when an object has soft, weak and phantom references to it:
The object is strongly reachable as long as there's a reference to it; either in a static field, an instance field of another strongly reachable object, or a local variable that is currently within scope.
When there are no more strong references to the object, it becomes softly reachable. Softly reachable objects stay softly reachable until the garbage collector determines that memory is running out, and they need to make room for other objects. The garbage collector then "clears" all the soft references (meaning, the soft reference will no longer refer to the object it used to refer to), and enqueues the references.
After that, the object becomes weakly reachable. The garbage collector will immediately clear all weak references to the object, and enqueue them. The object is then eligible for finalization.
Now, the garbage collection will run the finalize() method on the object, if it hasn't already done so. After the finalize() method is done, the object is finalized, and should** become phantom reachable. So an object that's phantom reachable only has phantom references to it. Phantom reachable objects are removed from memory; the space they take up is reclaimed by the garbage collector.
Phantom references are a special case. They *always* return null when asked about their referent. This is to prevent people from getting strong references to the object after it's been finalized. Secondly, phantom references aren't automatically cleared by the garbage collector before they are enqueued. You need to clear them manually after you've retrieved them from the reference queue, and performed cleanup operations.
Once all the phantom references to the object have been cleared or finalized, the object is no longer reachable. The object is unreachable.
I'll give some examples of use cases for these references. Soft references are only cleared when the JVM runs out of memory (this actually isn't a guarantee, the garbage collector may clear the references even if there's plenty of space). Therefore, they are great for building caches. They keep an object in memory as long as there's space, but they don't prevent the object from being collected when space runs out.
Weak references are great when you want to store extra information about an object, but that information is only useful for as long as the object exists. You can then have a weak reference to the object, which also strongly refers to the extra information. When the object has no strong references to it anymore, it becomes weakly reachable, is automatically cleared, and the weak reference is enqueued. The thread that deals with the reference queue can then clean up the extra information when it retrieves the weak reference from the queue.
Finally, Phantom references are good for two things only. One is determining that the object is *really* dead and removed from memory. The second thing is performing cleanup. If you need to clean up a bunch of other objects when the first object is dead, you can do so, and then clear the phantom reference. This is exactly the same as just performing the finalize() method, except it's safer, because the finalize() method can perform cleanup before the object is physically removed from memory.
**An object that has been finalized *should* become phantom reachable. However, this is not always true. The finalize() method can resurrect a dead object by storing a reference to it in a variable, thereby making it strongly reachable once again. This is why cleanup in the finalize() method is dangerous. It's possible to clean up other objects, but then resurrecting the original object. When you perform operations on the object, the program may fail catastrophically.
The mind is a strange and wonderful thing. I'm not sure that it will ever be able to figure itself out, everything else, maybe. From the atom to the universe, everything, except itself.
Here's a program that attempts to demonstrate these concepts. It's important to note that it may fail, because the garbage collector can not be forced to run. Also, the output may vary from run to run, because it uses 3 different threads without synchronization: the main thread, the reference queue thread, and the garbage collector thread.
If testSoft and testResurrection are false, then the garbage collector should be able to determine that the object is weakly reachable in the first pass, and immediately finalize it. In the second pass it will then determine that the object is phantom reachable, because the object wasn't resurrected.
If testSoft is true, the object becomes softly reachable in the first pass, and it should stay softly reachable until memory is filled up and the second pass clears the soft reference and determines that the object is weakly reachable, at which point it will finalize the object. Finally, in the third pass, the object is determined to be phantom reachable.
If testResurrection is true, the object is once again determined to be weakly reachable in the first pass, and promptly finalized. However, because the object is resurrected during finalization, the object will not be phantom reachable after the second and third passes. Before the fourth pass, the strong reference to the object is removed again, and for a second time the garbage collector determines that the object is weakly reachable. However, this time there will be no finalization because the garbage collector finalizes each object only once. Instead, the object is immediately made phantom reachable.
If both testSoft and testResurrection are true, the following process should happen:
- In the first pass, the object becomes softly reachable
- After filling all the memory, in the second pass the garbage collector clears the soft reference, enqueues it, and clears and enqueues the weak reference after which the object is finalized.
- Nothing happens in the third pass, because the object was resurrected, so it doesn't become phantom reachable
- Nothing happens in the fourth pass either, because the object becomes softly reachable and there's still plenty memory
- Memory is filled once again, and in the fifth pass the new soft and weak references are cleared and enqueued, *and* the object becomes phantom reachable because the finalize step isn't repeated.
- Nothing happens in the sixth step. Everything has been done.
It's worth to note that once soft and weak references are enqueued, they no longer refer to their original referent, because the garbage collector automatically clears them. It should also be evident at the start of the program that phantom references *always* point to null, regardless of whether their referent is phantom reachable.