General Strategy to Resolve Java Memory Leak

General strategy to resolve Java memory leak?

If you are using Java from Sun and you use at least Java 6 update 10 (i.e. the newest), then try running jvisualvm from the JDK on the same machine as your program is running, and attach to it and enable profiling.

This is most likely the simplest way to get started.

how to fix memory leak?

Profilers are usually helpful in finding memory leaks in complex programs. But if the program in question is small, you can try to find the memory leaks by carefully reading through the source code.

Think about following questions while you are reading the source code:

  1. What action is your program doing
    repeatedly? What objects are being
    created during this actions?
  2. Which of the created objects are needed by
    the program after the action is
    completed?
  3. Which objects are created once (for example at program
    startup) and remain in the memory
    till the end?
  4. Do any of the objects identified in earlier steps are reachable from the objects identified in step #3. If you find that some objects that are discard-able are reachable from objects from step #3 think about how can you break this reachability.

How can I create a memory leak in Java?

Here's a good way to create a true memory leak (objects inaccessible by running code but still stored in memory) in pure Java:

  1. The application creates a long-running thread (or use a thread pool to leak even faster).
  2. The thread loads a class via an (optionally custom) ClassLoader.
  3. The class allocates a large chunk of memory (e.g. new byte[1000000]), stores a strong reference to it in a static field, and then stores a reference to itself in a ThreadLocal. Allocating the extra memory is optional (leaking the class instance is enough), but it will make the leak work that much faster.
  4. The application clears all references to the custom class or the ClassLoader it was loaded from.
  5. Repeat.

Due to the way ThreadLocal is implemented in Oracle's JDK, this creates a memory leak:

  • Each Thread has a private field threadLocals, which actually stores the thread-local values.
  • Each key in this map is a weak reference to a ThreadLocal object, so after that ThreadLocal object is garbage-collected, its entry is removed from the map.
  • But each value is a strong reference, so when a value (directly or indirectly) points to the ThreadLocal object that is its key, that object will neither be garbage-collected nor removed from the map as long as the thread lives.

In this example, the chain of strong references looks like this:

Thread object → threadLocals map → instance of example class → example class → static ThreadLocal field → ThreadLocal object.

(The ClassLoader doesn't really play a role in creating the leak, it just makes the leak worse because of this additional reference chain: example class → ClassLoader → all the classes it has loaded. It was even worse in many JVM implementations, especially prior to Java 7, because classes and ClassLoaders were allocated straight into permgen and were never garbage-collected at all.)

A variation on this pattern is why application containers (like Tomcat) can leak memory like a sieve if you frequently redeploy applications which happen to use ThreadLocals that in some way point back to themselves. This can happen for a number of subtle reasons and is often hard to debug and/or fix.

Update: Since lots of people keep asking for it, here's some example code that shows this behavior in action.

Running out of memory in Java

As of JDK 6 a profiling tool called jvisualvm is included in the \bin directory. You can scan CPU usage, monitor memory and threads, etc.

You can read more about it here.

Memory Leak in practical example

Yes, you do have a memory leak in FadeRunnable class.

Every instance of inner class contains implicit reference to its outer class, accessible through OuterClass.this operator. In your project, when you execute the FadeRunnable and then trigger reconfiguration by orientation change, the whole activity and your CircularProgressView contained within get recreated, but the FadeRunnable from previous is still alive (allocated) and, because of it holding implicit reference to its outer CircularProgressView class, the view continues to live also, that's why after several reconfigurations you have 8 instances of CircularProgressView allocated in memory, and that gets worse - every View keeps a reference to it's context, and this cannot be freed also, resulting in bad memory leaks.

Runnables, Handlers and similar objects that can out-live their enclosing activities, fragments, views etc. should be declared as standard classes or STATIC inner classes (a static inner class doesn't hold implicit reference to its outer class), and shouldn't keep references such as Context, View etc., instead you can keep a WeakReference<> so when your Activity is recreated through config change, the View can be destroyed and freed by garbage collector.

This is a very informative article on the subject, I strongly suggest reading it.

how to release memory after java programme execution

Have the Java process exit when it is done with the job; use another scheduler (like cron) to start the Java process again in four hours.

How to deal with java.lang.OutOfMemoryError: Java heap space error?

Ultimately you always have a finite max of heap to use no matter what platform you are running on. In Windows 32 bit this is around 2GB (not specifically heap but total amount of memory per process). It just happens that Java chooses to make the default smaller (presumably so that the programmer can't create programs that have runaway memory allocation without running into this problem and having to examine exactly what they are doing).

So this given there are several approaches you could take to either determine what amount of memory you need or to reduce the amount of memory you are using. One common mistake with garbage collected languages such as Java or C# is to keep around references to objects that you no longer are using, or allocating many objects when you could reuse them instead. As long as objects have a reference to them they will continue to use heap space as the garbage collector will not delete them.

In this case you can use a Java memory profiler to determine what methods in your program are allocating large number of objects and then determine if there is a way to make sure they are no longer referenced, or to not allocate them in the first place. One option which I have used in the past is "JMP" http://www.khelekore.org/jmp/.

If you determine that you are allocating these objects for a reason and you need to keep around references (depending on what you are doing this might be the case), you will just need to increase the max heap size when you start the program. However, once you do the memory profiling and understand how your objects are getting allocated you should have a better idea about how much memory you need.

In general if you can't guarantee that your program will run in some finite amount of memory (perhaps depending on input size) you will always run into this problem. Only after exhausting all of this will you need to look into caching objects out to disk etc. At this point you should have a very good reason to say "I need Xgb of memory" for something and you can't work around it by improving your algorithms or memory allocation patterns. Generally this will only usually be the case for algorithms operating on large datasets (like a database or some scientific analysis program) and then techniques like caching and memory mapped IO become useful.

ThreadLocal & Memory Leak

PermGen exhaustions in combination with ThreadLocal are often caused by classloader leaks.

An example:

Imagine an application server which has a pool of worker threads.

They will be kept alive until application server termination.

A deployed web application uses a static ThreadLocal in one of its classes in order to store some thread-local data, an instance of another class (lets call it SomeClass) of the web application. This is done within the worker thread (e.g. this action originates from a HTTP request).

Important:
By definition, a reference to a ThreadLocal value is kept until the "owning" thread dies or if the ThreadLocal itself is no longer reachable.

If the web application fails to clear the reference to the ThreadLocal on shutdown, bad things will happen:

Because the worker thread will usually never die and the reference to the ThreadLocal is static, the ThreadLocal value still references the instance of SomeClass, a web application's class - even if the web application has been stopped!
As a consequence, the web application's classloader cannot be garbage collected, which means that all classes (and all static data) of the web application remain loaded (this affects the PermGen memory pool as well as the heap).

Every redeployment iteration of the web application will increase permgen (and heap) usage.

=> This is the permgen leak
One popular example of this kind of leak is this bug in log4j (fixed in the meanwhile).



Related Topics



Leave a reply



Submit