Memory Leak
  • The standard definition of a memory leak is a scenario that occurs when objects are no longer being used by the application, but the Garbage Collector is unable to remove them from working memory – because they’re still being referenced.
  • As a result, the application consumes more and more resources – which eventually leads to a fatal OutOfMemoryError.
  • We will see few scenarios.
Autoboxing
public class Adder {
   public long addIncremental(long l)
   {
		Long sum=0L;
		sum =sum+l;
		return sum;
   }
   public static void main(String[] args) {
		Adder adder = new Adder();
		for(long i;i<1000;i++)
		{
			adder.addIncremental(i);
		}
   }
}
  • Instead of taking the primitive long for the sum, we took the Long (wrapper class), which is the cause of the memory leak.
  • Due to auto-boxing, sum=sum+l; creates a new object in every iteration, so 1000 unnecessary objects will be created.
Using Cache
public class Cache {
       private Map<String,String> map= new HashMap<String,String>();
       public void initCache()
       {
              map.put("Ashish", "Work as Engineer");
              map.put("Rishab", "Work as Java Engineer");
              map.put("Arun", "Work as Doctor");
       }
       public Map<String,String> getCache()
       {
              return map;
       }
       publicvoid forEachDisplay()
       {
              for(String key : map.keySet())
              {
                String val = map.get(key);                 
                System.out.println(key + " :: "+ val);
              }
       }
       public static void main(String[] args) {            
              Cache cache = new Cache();
              cache.initCache();
              cache.forEachDisplay();
       }
}
  • Here, a memory leak occurs due to the internal map data structure. This class is to display the employee value from the cache.
  • Once those are displayed, there is no need to store those elements in the cache.
  • We forgot to clear the cache, so although objects in cache are not required anymore by the application, it can’t be GCed, as map holds a strong reference to them.
  • Alternatively, you can initialize cache by WeakHashMap.
  • The beauty of WeakHashMap is, if keys are not referenced by any other objects, then that entry will be eligible for GC.
Closing Connections
try
{
	Connection con = DriverManager.getConnection();
 	...
	con.close();
}
catch(exception ex)
{
}
  • In the above example, we close the connection (Costly) resource in the try block, so in the case of an exception, the connection will not be closed.
  • So it creates a memory leak as this connection never return back to the pool.
  • Please always put any closing stuff in the finally block.
Using CustomKey

public class CustomKey {
	public CustomKey(String name)
	{
  		this.name=name;
	}
	
	private String name;

	public static void main(String[] args) {
	      Map<CustomKey,String> map = new HashMap<CustomKey,String>();
	      map.put(new CustomKey("Shamik"), "Shamik Mitra");
	      String val = map.get(new CustomKey("Shamik"));
	      System.out.println("Missing equals and hascode so value is not accessible from Map " + val);
	}
}
  • As in CustomKey we forgot to provide equals() and hashcode() implementation, so a key and value stored in map can’t be retrieved later, as the map get() method checks hashcode() and equals().
  • But this entry is not able to be GCed, as the map has a reference to it, but application can’t access it. Definitely a memory leak.
  • So when you make your Custom key, always provide an equals and hashcode() implementation.

 

Categories: JAVA

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.