Reference in Java – part 2
In the last edition , we discussed about concept of referencing in java , GC and its stages ( basic knowledge) and about strong and weak references.
In our day to day life this would suffice our basic needs with certain memory rules in mind while coding . But there are occasions where we need to write highly data intensive code . These are the places where we need to be very sure about the data creation , data maintenance and data destruction.
In this article we would discuss about other 2 forms of References provided by Java i.e. Phantom Reference and Weak Reference
Java has been a language where Naming conventions have been spot on . Most of the things are self explanatory . Nothing changes here too !! As the name suggest this type of references are phantoms . Like the comic phantom , this also doesn’t posses any magical powers but relies on its intelligence and of-course you cant catch them.
So lets first understand what Java Doc Says about them
As in the case of Weak Reference as and when JVM realizes that for a given object , there is no other reference left for the object other than phantom reference then it adds this phantom reference to the assigned queue.
Another interesting fact what Java Doc Says about Phantom References
This is something which makes these type of references Phantom , because they do exist but can't be seen.
Now this is pretty important : As we saw in last edition that once all strong/soft references to an object which also has a weak reference is removed , then automatically the object is removed from Memory without waiting for the weak reference to go .
But this is not a case with Phantom References , the object is still present in memory until or unless all phantom references are removed.
So enough of theory and lets proceed with the example and understand how does it works:
Now lets see the result of this piece of Code and dig in step by step
(1) & (2) Here we create a Reference queue and a Phantom reference object assigned to that queue. Its very similar to how we had done for Weak Reference . Nothing new here!!
(3) Here we try to print our first sysout by polling the queue and as expected we get back null as there is nothing in the queue which has been added
(4) This is the place where magic starts , in case of weak reference , if you use its 'get' method , then you are provided with the original object on which this weak reference was created . But in case of phantom reference 'get' method always return null . As mentioned this is one of the reasons why its called phantom references.
(5) All the work starts once the strong reference goes off , so at this point we remove the strong reference to the object and then wait for 15 sec's (hoping) grabage collector runs and starts its work
(6) But as we know that there is no guarantee of garbage collector so we run the command at least trying to intimate JVM about our intentions.
(7),(8),(9) & (10) Now as the object has lost all strong reference and is only left with phantom reference , so this phantom reference should be added to its respective queue. But its much easier said then done . GC is a much complicated program , its generally not possible to do all stuffs in one go . So if you are lucky you would be entering line (8) (unfortunately I wasn't) . So to be sure that phantom reference is added in the queue , we iterate couple of time (in my case it was the 4 attempt) to get the phantom reference in queue
(11) Generally 1000 iterations should be good to get a result , but even if we don’t get then we might have some trouble .
Question : What sort of trouble , I'll leave it you to think , If not found you call always shoot mail to us , we'll send it to you
(12) Now lets go back to what we stated about phantom reference before starting the example, the objects which are referenced by phantom references will remain till all phantom references are not lost . So because of this we need to explicitly set phantom reference to null , so that object can be removed
What is a difference between Weak Reference and Phantom reference
Now when you look at these 2 entities they look pretty similar and might be confusing when to use one and when to use another
The difference is very subtle.
As we discussed last time that GC process is a 3 step process
1) Checking if object is not reachable , if Yes
a) Check if object implements finalize() method , if so add to finalization queue
b) Else , make the object finalized
2) If (a) section of Point (1) was true , then pick the object from finalization queue and run the finalize method and make object finalized
3) Garbage collector picks the object and de–allocates the memory
In case of Weak reference once the strong reference goes to null , weak reference is added to the queue , weak reference's pointer to the object is removed (basically 'get' method would return null) , this weak reference is added to the queue and object is prepared for finalization (scheduled for final method call if it exists). So by the time you pick soft reference from queue , the final method might or might not have run.
Now in case of phantom reference the phantom reference is only added only after it has been finalized i.e. finalize method has been invoked.
Now lets discuss about the 4 type of reference : Soft Reference
Soft References are pretty similar to Weak Reference’s so we won't dig too deep inside that . The syntax are pretty same , so if you have a code with weak reference , you can substitute weak reference with soft reference and your code is ready.
Now lets discuss difference between them
Soft reference's are little slower as compared to weak reference's . So if a object having soft references looses all its strong reference's , it won't be removed immediately . GC would wait for a stage where it feels that it is running out of memory . At this point it will start removing all objects which have soft reference's and starts vacating some space.
JVM gives you a guarantee that , if its throwing 'OutOfMemory” error , it has tried its best to vacate all unnecessary objects and all objects left with soft reference's are removed for sure.
But as always again Java is very friendly , its gives you an option to hint the JVM when it should start removing these objects
There is a jvm parameter 'SoftRefLRUPolicyMSPerMB' . You can fine tune your JVM settings with this parameter . But we should try avoiding this because Java Doc says :
Soft reference's are pretty useful , when you intend to implement some sort of programmatic caching . You can make these objects as soft reference so that java automatically removes them when space crunch starts
In the next article we would discuss some of the Java provided ways to analyze heap (will not dig into any tool stuff )