What is Strong, Soft, Weak and Phantom Memory References in Java

Understanding various available reference objects in Java is quite important to develop memory sensitive applications, and for memory optimization. Java has four type of memory references which are
  • Strong References,
  • Soft References,
  • Weak References and 
  • Phantom References
However to understand the use of these reference objects, we need to understand in brief that how Java manage the memory, and how it manage the garbage. Please refer to other post at 'How does Java Manage the Memory' to understand that. Now if you are clear with the Java Memory Management Concept, understanding various kind of memory references in Java would be easy for you. The description below is given considering that the readers have read the other post as given above (How does Java Manage the Memory).

Strong Reference: The objects in memory which are referenced from memory stack (without a reference through any other kind of reference) are called strongly referenced. These objects are strongly held by program i.e. in use and hence can not be claimed by GC (Garbage Collector) for memory requirement.

Soft Reference: These objects are also referenced from memory stack but through Soft Reference Objects. Soft Reference is a special object provided by Java API. Any object referenced by memory stack through Soft Reference is available to GC to recollect; however GC try not to do so as much as it is possible. So Soft References keep in memory till the system does not face acute shortage of memory and there is no other option but to reclaim the memory occupied by Soft References.GC can be configured to collect the soft references less or more aggressively.

The objects maintained by soft reference objects are referenced softly, however they are reference strongly if they are in use by program. As soon as, program will stop using these objects, these will again be softly referenced through soft reference object.

Soft references are generally used for creating the cache. When we need to use some heavy objects again and again, these can be cached in memory using Soft References. This way, we can save the system processing to recreate these heavy objects again and again; and the GC can claim these heavy objects in case of memory requirement. However keep in mind that the objects to cache should be heavy in size otherwise cleaning the memory itself will be a heavy process as GC need to traverse a number of objects to claim required level of memory.

Soft references can also be used to avoid 'out of memory' exception. Whenever we are doing any memory sensitive operations which consumes a lot of memory, we can use soft reference object to see whether there is pressure on memory or not. We can create a soft reference object before running the actual logic and keep checking the soft reference for its referent. If soft referent is null, we can understand that there is some pressure on memory and hence through the custom exception to raise their erroneous condition and can release the memory.

Weak Reference: Weak references are just like soft references, but the difference is that GC claim it as soon as there is any memory requirement. It does not wait till there is acute shortage of memory like it does in case of Soft Reference. So if referent object of weak reference is not referenced by any strong link or soft reference, it is guaranteed to be collected as soon there is any memory requirement.

Weak reference are used when we have some references which are actually not having any inherent relationship with the object. We can take example of ObjectOutputStream. OOS keep the reference of all the objects it serialize till we close it or we can reset method on it. So if we forget to call the reset or to close it, any object which is being released by actual program can be in memory due to OOS. So if we use weak references here to refer the objects, this problem can be resolved.

Other example is like if we want to keep track of all objects of a particular type in the memory. We can register all of these objects to a weak hash map from their constructor itself. So it gives us the option to access all the objects active in memory at any point of time, and also release the objects as soon as the strong reference is released.

Phantom Reference:

Before understanding the Phantom reference, we should understand the Reference Queue first. Reference queue is used to track the objects claimed by GC. We can use the reference objects to check whether the objects referred by these are still active or are claimed by GC. This can be done by checking the object reference with reference objects. But if you have a lot of references, it would be a long process to check all the references and their referenced objects. But as alternative, we can register the references with Reference Queue. As soon as any referent object of reference is claimed by GC, the reference will be added to the Reference Queue. So we can just keep polling the Reference Queue to check that whether any object has been claimed by GC or not, rather than to traverse on all the references.

Not let us talk about Phantom References now. Phantom references are not used like Soft or Weak Reference to access their referenced objects. Rather it is used to know that referenced objects has been collected by GC. So this reference is mainly used for cleanup purpose like we use 'finalize' method.

We know that finalizers can be used for cleanup process. However finalizer has its own drawback, like if finalize method takes a lot of time in its processing then it will block the whole process. Try to add Thread.sleep in finalize method and your whole program will be hang. So alternatively, Phantom references can be used here as you can traverse the claimed references once they are claimed by GC. This is the use of Phantom Reference.

A few weaknesses of 'finalize' methods are:

  • It is possible that finalize method never calls for an object in its lifetime because JVM never feels like shortage of memory. 
  • Finalize method is called only once for any object. So if any object resurrect itself from finalize method, its finalize method will never be called again. This is not exactly weakness, however it is a design decision. 
  • Finalize method is called after some gap of uncertainty or discontinuity, like GC first mark all the objects to claim and then it calls the finalize method on these objects and claim their memory. So there is no continuity between identifying and calling the finalize method. And visualize a scenario, when the only object which is available for GC is having a finalize method with some code to process. Now if the system is on the verge of out of memory before calling the GC, it will actually can not escape from out of memory, as finalize method have to be called on the object. 

People who read this post also read :


Anonymous said...

Nice one Mohit.... Thank you...

Mohit Gupta said...

Refer to http://www.kdgregory.com/index.php?page=java.refobj for Practical Example of Phantom References.

Post a Comment