Thursday, 25 April 2013

What is Memory Leak in Java?


Memory Leak

The Java completely relies on automatic garbage collection process, which typically operates as a low-priority thread that constantly searches memory from unreachableobjects, objects that are not referenced by any other object reachable by a live thread. Different JVMs use different algorithms to determine how to collect garbage objects in the best efficient way. 
  
What is Memory Leak in Java?

Ans: -In java, it’s a kind of situation where some objects are not used by application any more, but GC unable or fails to recognize them as unused. As a result, these objects remain in memory for indefinite amount of time reducing the amount of memory available to the application. Or in other terms we can say that when a java application consumes memory but it is unable to release back to OS.

Question: -How can Garbage Collector differentiate between the unused objects and the objects which is used by the application?

Ans: -The basic algorithm which Garbage Collector uses can be described as follows:
  • There are few objects which are considered “important” by GC. These are called GC roots and are (almost) never discarded. They are, for example, currently executing method’s local variables and input parameters, application threads, references from native code and “global” objects.
  • Any object referenced from those GC roots are assumed to be in use and not discarded. One object can reference another in different ways in Java, most commonly being when object X is stored in a field of object Y. In that case, we say “Y references X”. The above process is repeated until all objects that can be transitively reached from GC roots are visited and marked as “in use”. (By Following Mark and Sweep algorithm).
  • Rest every objects is left unmarked and treated as unused and can be thrown away.

Consequences

A memory leak can depreciate the performance of the application by reducing the amount of available memory. In some cases,  very much of the available memory may become allocated to application and all other part of the system device stops working properly, the application fails, or the system slows down unacceptably due to thrashing.


Causes of memory leaks in Java

Below are the typical causes of memory leaks in a Java program:
  • Unknown object references:- These objects are no longer needed, but the garbage collector cannot able to identify and reclaim memory because another object still refers to it.
  • Long-live static/class objects:- These objects stay in the memory for the application's full lifetime. Objects tagged to the session may also have the same lifetime as the session still alive, which is created per user and remains until the user logs out of the application.
  • Failed to clean up and reclaim memory from native system resources:- Native system resources are allocated by a function external to Java, typically native code written in C or C++. Java Native Interface (JNI) APIs are used to embed native libraries/code into Java code.
  • Use of Error prone third-party libraries: Bugs in various versions of the JDK/ third party libraries or bugs in the Abstract Window Toolkit(AWT) and Swing packages are also responsible for memory leaks.
  • Consumption of more memory by application: - It is also responsible for causing memory leaks. Root is inefficiently configured caches are the typical causes for high memory usage.
  • By the use of Collections and Mutable Static Fields:- Static fields are GC roots means they are never garbage-collected. Conveniently, static fields and collections are often used to hold caches for application or share state across threads in the application. Mutable static fields need to be cleaned up explicitly; automatically cleanup will not take place by GC, resulting in a memory leak.  Collections and Static fields have become the most common cause of memory leaks. So we can say that instead of using mutable static fields, we should use final constants.
  • Repeated use of Thread-Local Variables: - Basically thread-local variable is a member field in the Thread class. In a multithreaded environment, every thread instance has its own instance of such variable. Therefore it will be very useful to bind a state to a thread. But it will create a hazardous situation because thread-local variables will not be removed by the GC as long as the thread itself is alive because any active thread is considered as GC root. As we know threads are pooled and thus it is kept alive virtually forever in that application environment, and GC is not able to remove the thread-local variable object thus unable to reclaim memory, So to overcome from this situation, we explicitly clean it up or we should avoid using this or rarely we should use this. 


  • By Over-riding of finalize() method – Many Java classes override the finalize () method to free up system resources before the GC runs. There’s no guarantee that it will run or not. The JVM doesn’t garbage collect the objects whose finalize () method has not been run. Consequently, such object exists in memory even though they could no longer be referenced by the application and lead for memory leaks in future.


Note: - finalize() method is called by GC before collecting unreferenced objects. We have a choice which can give us a way for running of finalize method by calling Runtime.getRuntime().runFinalization() or System.runFinalization(). These methods are capable for ensuring that JVM can call finalize() method of all object which are eligible for garbage collection and whose finalize has not yet called.
 
Detection of memory leaks

An approach to detect memory leaks is listed below:
  • By using Runtime class totalMemory() and freeMemory() methods, which shows how much total heap memory is being controlled by the JVM, along with how much is not in use at a particular time. This mechanism can provide the heap's memory utilization.
  • By using memory-profiling tools, like JProbe Memory Debugger. These tools can provide a runtime picture of the heap and its utilization. However, they can be used only during development, not deployment, as they slow down the application performance considerably.
  • By using OS (operating system) process monitor, which informs how much memory a process is using. In Windows, the task manager can show memory usage when a Java program is running. This mechanism gives an idea of total memory utilization of a java process's / application.
  • By using AppDynamics tool: - It is the best solution for memory leak identification and solution tool. Even this tool also helps us in Java production environment. AppDynamics is the leading provider of application management for modern application architectures in both the cloud and the data center, delivering solutions for highly demanding distributed, dynamic, and agile environments.
  • By using VisualVM: - A tool providing powerful profiling capabilities by integrating some of the commands of JDK tools. It allows us to analyze heap data, tack down memory leaks, monitoring the GC and also allow for memory optimization. It is a part of JDK from jdk1.6 update 7 onwards. So if  we have any version of JDK1.6 since update 7 then VisualVM(jvisualvm.exe) is available in JDK bin directory.




No comments:

Post a Comment