By Mat B.


2011-06-24 16:11:52 8 Comments

I just had an interview, and I was asked to create a memory leak with Java.
Needless to say, I felt pretty dumb having no clue on how to even start creating one.

What would an example be?

30 comments

@Daniel Pryden 2011-06-24 18:05:10

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.

@earcam 2011-06-27 16:55:16

+1 ClassLoader leaks are some of the most commonly painful memory leaks in the JEE world, often caused by 3rd party libs that transform data (BeanUtils, XML/JSON codecs). This can happen when the lib is loaded outside your application's root classloader but holds references to your classes (eg. by caching). When you undeploy/redeploy your app the JVM is unable to garbage collect the app's classloader (and therefore all classes loaded by it), so with repeat deploys the app server eventually borks. If lucky you get a clue with ClassCastException z.x.y.Abc cannot be cast to z.x.y.Abc

@bestsss 2011-06-30 19:49:07

tomcat uses tricks and nils ALL static variables in ALL loaded classes, tomcat has a lot of dataraces and bad coding though (need to get some time and submit fixes), plus the all mind-boggling ConcurrentLinkedQueue as cache for internal (small) objects, so small that even the ConcurrentLinkedQueue.Node takes more memory.

@Adrian M 2011-07-08 09:08:02

+1: Classloader leaks are a nightmare. I spent weeks trying to figure them out. The sad thing is, as what @earcam has said, they are mostly caused by 3rd party libs and also most profilers can't detect these leaks. There's a good and clear explanation on this blog about Classloader leaks. blogs.oracle.com/fkieviet/entry/…

@Nicolas Raoul 2011-07-11 06:39:47

+1 Note that it will leak on HotSpot but not on JRockit.

@Daniel Pryden 2011-07-11 17:01:49

@Nicolas: Are you sure? JRockit does GC Class objects by default, and HotSpot doesn't, but AFAIK JRockit still can't GC a Class or ClassLoader that is referenced by a ThreadLocal.

@Matthijs Bierman 2012-03-02 10:33:03

Tomcat will try to detect these leaks for you, and warn about them: wiki.apache.org/tomcat/MemoryLeakProtection. The most recent version will sometimes even fix the leak for you.

@Nikem 2012-09-11 06:06:55

For future references, there is one more tool trying to solve classloader leaks: Plumbr

@DiveInto 2012-11-12 05:23:15

@DanielPryden Does this gist(gist.github.com/4057644) shows what you described? but it won't go out of memory according to my test,correct me if there is any misunderstanding,thanks

@DiveInto 2012-11-15 03:24:42

@DanielPryden I have update my gist,please check: gist.github.com/4057644#gistcomment-595443

@Sid 2013-08-12 16:58:16

Okay A little stupid question...Will it be termed as a memory leak,if the GC(Garbage Collector) doesn't kicks in? I am not sure whether one can invoke GC explicitly.

@Daniel Pryden 2013-08-14 00:10:37

@Sid: the issue is not whether or not the GC actually runs (Raymond Chen argues that a no-op GC is a valid implementation, see Everybody thinks about garbage collection the wrong way), it's whether, even if the GC did run, it would be unable to reclaim an object that is no longer visible to any running code. A ClassLoader leak is one way to end up with objects that cannot be found or used, but that still occupy memory and are rooted for GC purposes, so the GC cannot reclaim them.

@Jack 2014-05-14 02:54:00

It would be great if you could provide the code, I could not get all the steps! How to create one with a non-static member ? thanks.

@Daniel Pryden 2014-05-20 20:53:25

@JackMoore: I don't have "the code", this is just an example of a systemic problem. The issue is that a ThreadLocal creates a strong reference to an instance of a class, and through that instance to the class itself (and to all data statically reachable from the class), including the ClassLoader that loaded the class. But you can clear all references to the ThreadLocal object instance and not clear the underlying GC reference as long as the referenced Thread is still running. Basically, the Thread has an invisible, uncollectable reference to the ThreadLocal storage, which thus leaks.

@Daniel Pryden 2014-05-20 20:59:04

@AfterWorkGuinness: See my response to Jack Moore. Does that make sense? The Thread itself can be a GC root even if, for all other intents and purposes, there are no more references to the given value reachable from Java code. If you have a thread pool and you load and unload classes using a ClassLoader, it's entirely possible that any particular thread in the pool may outlive the classes, and can this keep a large amount of memory (all classes in the ClassLoader, and all data statically reachable from any of them) "reachable" for GC purposes although the values can't be reached from code.

@AfterWorkGuinness 2014-08-22 15:31:56

@DanielPryden could you post a code snipped for this ? I'm having trouble visualizing it.

@Daniel Pryden 2015-04-11 22:43:12

@igaurav: Regarding your edit to this answer, please see the discussion at meta.stackoverflow.com/questions/289814

@Tamas Hegedus 2016-04-03 19:17:07

I think this is not a "true" memory leak. One could still retrieve the loaded classes by investigating the Thread object's package visible threadLocals member field via reflection. So this isn't a more "true" leak than a simple unused private field.

@Daniel Pryden 2016-04-03 21:41:29

@TamasHegedus: It's true that you can find specific cases of this using reflection, but that only works if the installed SecurityManager allows it, and it also depends on you being able to programmatically identify a type as being no longer in use. In a constrained case this is certainly doable, but I don't think it solves the general case.

@Tony 2016-04-25 14:57:09

I am not sure whether I understand you right: The thread own the ThreadLocalMap which own threadLocal variable and class. But the content in ThreadLocalMap is weakly reachable, shouldn't it be GCed when memory is not enough?

@Daniel Pryden 2016-04-26 05:52:09

@Tony: Each Thread holds strong references to every ThreadLocal. So the ThreadLocal values can't be GC'd as long as the thread keeps running. This kind of problem often surfaces in an application container that owns a thread or thread pool that runs as long as the JVM does, which effectively keeps the garbage rooted forever. You're right though that if you ensure that all threads that could possibly be holding a ThreadLocal have been forcibly terminated, you can fix the leak. But in a large application that can often be an intractable task.

@Tony 2016-04-26 06:26:37

Sorry, but I can't find any reference about 'Each Thread holds strong references to every ThreadLocal.'. From source, the ThreadLocalMap's Entry is extended from WeakReference, shouldn't it mean the entry may be GCed when no strong reference to the entry holds? Thank you.

@Daniel Pryden 2016-04-26 15:08:18

@Tony: the Javadoc on ThreadLocal says: "Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible". Empirically this prevents a Class object for the type of value stored in a ThreadLocal from being GC'd while the thread is running: see the Gist I linked to in my answer for an example.

@Tony 2016-04-27 02:03:24

Oh, the class also have a strong reference to its static field(ThreadLocal in this case), so this make ThreadLocal stay in memory. Isn't it?

@Brian Bulkowski 2017-04-18 18:09:06

When I ask a question in an interview, especially like this, the answer isn't "here's how you do it". I make a point of asking questions that don't have a look-it-up-on-stackoverflow answer. Instead, I expect a discussion about what a memory leak is, how java works, the internal data structures. I am hoping for "If you mean having a process consume a ton of memory and halt, there are a bunch of ways, I can show you a handful. Is that what you want? It's not technically a leak though." ( Then code it in 2 lines ). Or tell a war story about tracking one down. That's the person I want to hire.

@AMDG 2017-09-05 22:04:46

Note that, since Java 8, there is no longer a permgen but the Metaspace. Memory leaking still persists, but the main difference besides the name is that Metaspace size can be auto-incremented.

@Philip Rego 2017-09-08 20:14:44

I'm getting a recourse leak. I'm calling Class.forName("com.informix.jdbc.IfxDriver"); in a scheduled thread. Would that cause a resource leak? @TamasHegedus

@Tamas Hegedus 2017-09-09 08:30:43

@philiprego no, that wouldn't as far as you load the same driver every time

@Artanis Zeratul 2018-12-11 22:35:49

@community wiki, so what if I can't get away with long running threads? like I need to fetch something perpetually from the DB or somewhere else?

@Daniel Pryden 2018-12-11 22:45:53

@ArtanisZeratul: It sounds like you're trying to ask a new question. You can do that by clicking "Ask Question". And "community wiki" isn't a person, it just means that all of the answers to this question are owned by the whole community rather than individuals.

@Malcolm 2019-03-01 17:15:48

Why this elaborate scheme with the ClassLoader though? Why isn't it enough to create some objects and put them into ThreadLocal?

@Daniel Pryden 2019-03-01 18:24:32

@Malcom: The reason the ClassLoader makes a difference is because, if you lose the reference to the Class that contained the reference to the ThreadLocal, you no longer have any way to get a reference to the ThreadLocal object. So the memory is leaked because you can't write code that can remove, or even retrieve, the leaked object anymore.

@jcsahnwaldt says GoFundMonica 2019-11-23 15:17:18

@DanielPryden: @Malcom is right. When the value of the ThreadLocal points back to the ThreadLocal object itself (maybe directly, or through some intermediate references), there's a leak. It doesn't matter if the intermediate references are in a ClassLoader or not. Here's a small example that creates a memory leak simply by creating a ThreadLocal object that directly points back to itself: repl.it/@jcsahnwaldt/ThreadLocalLeakExample

@jcsahnwaldt says GoFundMonica 2019-11-23 15:27:27

@Tony: "Oh, the class also have a strong reference to its static field (ThreadLocal in this case), so this make ThreadLocal stay in memory. Isn't it?" - Well, the main thing is that the value of the ThreadLocal is a (direct or indirect) reference to the ThreadLocal itself. Due to some details of the ThreadLocal implementation in Sun's/Oracle's JDK, this creates a leak. The exact reference path to the ThreadLocal - whether directly, through static fields, or through instance fields - doesn't matter.

@jcsahnwaldt says GoFundMonica 2019-11-23 15:32:07

By the way, the original implementation of ThreadLocal in JDK 1.2 didn't have that problem. Give it a try: download github.com/fanhongtao/.../jdk_1.2.1/.../ThreadLocal.java, remove the package declaration, and compile and run it with @DanielPryden's sample code - no memory leak! (That implementation had other problems though. Josh Bloch mentions some of them here: cs.oswego.edu/pipermail/concurrency-interest/2007-October/… )

@jcsahnwaldt says GoFundMonica 2019-11-23 15:42:27

@Jepessen: "I just don't understand why the thread must be long-running" - In Sun's/Oracle's implementation of ThreadLocal, thread-local values are actually stored in a map that is attached to the thread. When the thread dies, the garbage collector eventually clears this map, which would also remove the memory leak in this example. github.com/openjdk/jdk/blob/master/src/java.base/share/class‌​es/…

@Amir Forsati 2019-09-18 15:24:32

One of the java memory leakings examples is MySQLs memory leaking bug resulting when ResultSets close method is forgotten to be called. For example:

while(true) {
    ResultSet rs = database.select(query);
    ...
    // going to next step of loop and leaving resultset without calling rs.close();
}

@PlayTank 2011-07-01 20:06:10

The answer depends entirely on what the interviewer thought they were asking.

Is it possible in practice to make Java leak? Of course it is, and there are plenty of examples in the other answers.

But there are multiple meta-questions that may have been being asked?

  • Is a theoretically "perfect" Java implementation vulnerable to leaks?
  • Does the candidate understand the difference between theory and reality?
  • Does the candidate understand how garbage collection works?
  • Or how garbage collection is supposed to work in an ideal case?
  • Do they know they can call other languages through native interfaces?
  • Do they know to leak memory in those other languages?
  • Does the candidate even know what memory management is, and what is going on behind the scene in Java?

I'm reading your meta-question as "What's an answer I could have used in this interview situation". And hence, I'm going to focus on interview skills instead of Java. I believe you're more likely to repeat the situation of not knowing the answer to a question in an interview than you are to be in a place of needing to know how to make Java leak. So, hopefully, this will help.

One of the most important skills you can develop for interviewing is learning to actively listen to the questions and working with the interviewer to extract their intent. Not only does this let you answer their question the way they want, but also shows that you have some vital communication skills. And when it comes down to a choice between many equally talented developers, I'll hire the one who listens, thinks, and understands before they respond every time.

@DaveC 2011-07-03 17:59:17

Whenever I have asked that question, I am looking for a pretty simple answer - keep growing a queue, no finally close db etc, not odd classloader/thread details, implies they understand what the gc can and cannot do for you. Depends on the job you are interviewing for I guess.

@Daniel Newtown 2015-06-29 06:39:44

Please have a look at my question, thanks stackoverflow.com/questions/31108772/…

@Hearen 2019-03-28 07:25:30

a memory leak is a type of resource leak that occurs when a computer program incorrectly manages memory allocations in such a way that memory which is no longer needed is not released => wiki definition

It's kind of relatively context-based topic, you can just create one based on your taste as long as the unused references will never be used by clients but still stay alive.

The first example should be a custom stack without nulling the obsolete references in effective java item 6.

Of course there are many more as long as you want, but if we just take look at the java built-in classes, it could be some as

subList()

Let's check some super silly code to produce the leak.

public class MemoryLeak {
    private static final int HUGE_SIZE = 10_000;

    public static void main(String... args) {
        letsLeakNow();
    }

    private static void letsLeakNow() {
        Map<Integer, Object> leakMap = new HashMap<>();
        for (int i = 0; i < HUGE_SIZE; ++i) {
            leakMap.put(i * 2, getListWithRandomNumber());
        }
    }



    private static List<Integer> getListWithRandomNumber() {
        List<Integer> originalHugeIntList = new ArrayList<>();
        for (int i = 0; i < HUGE_SIZE; ++i) {
            originalHugeIntList.add(new Random().nextInt());
        }
        return originalHugeIntList.subList(0, 1);
    }
}

Actually there is another trick we can cause memory leak using HashMap by taking advantage of its looking process. There are actually two types:

  • hashCode() is always the same but equals() are different;
  • use random hashCode() and equals() always true;

Why?

hashCode() -> bucket => equals() to locate the pair


I was about to mention substring() first and then subList() but it seems this issue is already fixed as its source presents in JDK 8.

public String substring(int beginIndex, int endIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    if (endIndex > value.length) {
        throw new StringIndexOutOfBoundsException(endIndex);
    }
    int subLen = endIndex - beginIndex;
    if (subLen < 0) {
        throw new StringIndexOutOfBoundsException(subLen);
    }
    return ((beginIndex == 0) && (endIndex == value.length)) ? this
            : new String(value, beginIndex, subLen);
}

@Pavel Molchanov 2018-06-21 20:47:12

I want to give an advice on how to monitor application for the memory leaks with the tools that are available in JVM. It doesn't show how to generate the memory leak but explains how to detect it with minimum tools available.

You need to monitor Java memory consumption first.

The simplest way to do this is to use jstat utility that comes with JVM.

jstat -gcutil <process_id> <timeout>

It will report memory consumption for each generation (Young, Eldery and Old) and garbage collection times (Young and Full).

As soon as you spot that Full Garbage Collection is executed too often and takes too much time, you can assume that application is leaking memory.

Then you need to create a memory dump using jmap utility:

jmap -dump:live,format=b,file=heap.bin <process_id>

Then you need to analyse heap.bin file with Memory Analyser, Eclipse Memory Analyzer (MAT) for example.

MAT will analyze the memory and provide you suspect information about memory leaks.

@Marko Pacak 2018-04-26 12:21:53

Another way to create potentially huge memory leaks is to hold references to Map.Entry<K,V> of a TreeMap.

It is hard to asses why this applies only to TreeMaps, but by looking at the implementation the reason might be that: a TreeMap.Entry stores references to its siblings, therefore if a TreeMap is ready to be collected, but some other class holds a reference to any of its Map.Entry, then the entire Map will be retained into memory.


Real-life scenario:

Imagine having a db query that returns a big TreeMap data structure. People usually use TreeMaps as the element insertion order is retained.

public static Map<String, Integer> pseudoQueryDatabase();

If the query was called lots of times and, for each query (so, for each Map returned) you save an Entry somewhere, the memory would constantly keep growing.

Consider the following wrapper class:

class EntryHolder {
    Map.Entry<String, Integer> entry;

    EntryHolder(Map.Entry<String, Integer> entry) {
        this.entry = entry;
    }
}

Application:

public class LeakTest {

    private final List<EntryHolder> holdersCache = new ArrayList<>();
    private static final int MAP_SIZE = 100_000;

    public void run() {
        // create 500 entries each holding a reference to an Entry of a TreeMap
        IntStream.range(0, 500).forEach(value -> {
            // create map
            final Map<String, Integer> map = pseudoQueryDatabase();

            final int index = new Random().nextInt(MAP_SIZE);

            // get random entry from map
            for (Map.Entry<String, Integer> entry : map.entrySet()) {
                if (entry.getValue().equals(index)) {
                    holdersCache.add(new EntryHolder(entry));
                    break;
                }
            }
            // to observe behavior in visualvm
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

    }

    public static Map<String, Integer> pseudoQueryDatabase() {
        final Map<String, Integer> map = new TreeMap<>();
        IntStream.range(0, MAP_SIZE).forEach(i -> map.put(String.valueOf(i), i));
        return map;
    }

    public static void main(String[] args) throws Exception {
        new LeakTest().run();
    }
}

After each pseudoQueryDatabase() call, the map instances should be ready for collection, but it won't happen, as at least one Entry is stored somewhere else.

Depending on your jvm settings, the application may crash in the early stage due to a OutOfMemoryError.

You can see from this visualvm graph how the memory keeps growing.

Memory dump - TreeMap

The same does not happen with a hashed data-structure (HashMap).

This is the graph when using a HashMap.

Memory dump - HashMap

The solution? Just directly save the key / value (as you probably already do) rather than saving the Map.Entry.


I have written a more extensive benchmark here.

@Nicolas Bousquet 2011-07-01 07:54:01

Most examples here are "too complex". They are edge cases. With these examples, the programmer made a mistake (like don't redefining equals/hashcode), or has been bitten by a corner case of the JVM/JAVA (load of class with static...). I think that's not the type of example an interviewer want or even the most common case.

But there are really simpler cases for memory leaks. The garbage collector only frees what is no longer referenced. We as Java developers don't care about memory. We allocate it when needed and let it be freed automatically. Fine.

But any long-lived application tend to have shared state. It can be anything, statics, singletons... Often non-trivial applications tend to make complex objects graphs. Just forgetting to set a reference to null or more often forgetting to remove one object from a collection is enough to make a memory leak.

Of course all sort of listeners (like UI listeners), caches, or any long-lived shared state tend to produce memory leak if not properly handled. What shall be understood is that this is not a Java corner case, or a problem with the garbage collector. It is a design problem. We design that we add a listener to a long-lived object, but we don't remove the listener when no longer needed. We cache objects, but we have no strategy to remove them from the cache.

We maybe have a complex graph that store the previous state that is needed by a computation. But the previous state is itself linked to the state before and so on.

Like we have to close SQL connections or files. We need to set proper references to null and remove elements from the collection. We shall have proper caching strategies (maximum memory size, number of elements, or timers). All objects that allow a listener to be notified must provide both a addListener and removeListener method. And when these notifiers are no longer used, they must clear their listener list.

A memory leak is indeed truly possible and is perfectly predictable. No need for special language features or corner cases. Memory leaks are either an indicator that something is maybe missing or even of design problems.

@ehabkost 2011-07-22 06:12:36

I find it funny that on other answers people are looking for those edge cases and tricks and seem to be completely missing the point. They could just show code that keep useless references to objects that will never use again, and never remove those references; one may say those cases are not "true" memory leaks because there are still references to those objects around, but if the program never use those references again and also never drop them, it is completely equivalent to (and as bad as) a "true memory leak".

@SyntaxT3rr0r 2011-07-22 11:49:18

@Nicolas Bousquet: "Memory leak is indeed trully possible" Thank you so much. +15 upvotes. Nice. I got yelled at here for stating that fact, as the premises of a question about the Go language: stackoverflow.com/questions/4400311 This question still has negative downvotes :(

@supercat 2013-05-09 16:41:42

The GC in Java and .NET is in some sense predicated on the assumption graph of objects that hold references to other objects is the same as the graph of objects that "care about" other objects. In reality, it's possible that edges can exist in the reference graph that don't represent "caring" relations, and it's possible for an object to care about the existence of another object even if no direct or indirect reference path (even using WeakReference) exists from one to the other. If a object reference had a spare bit, it could be helpful to have a "cares about the target" indicator...

@supercat 2013-05-09 16:47:22

...and have the system provide notifications (via means similar to PhantomReference) if an object was found not to have anyone that cared about it. WeakReference comes somewhat close, but must be converted to a strong reference before it can be used; if a GC cycle occurs while the strong reference exists, the target will be assumed to be useful.

@nalply 2017-04-18 12:16:10

This is in my opinion the correct answer. We wrote a simulation years ago. Somehow we accidentally linked previous state to current state creating a memory leak. Because of a deadline we never resolved the memory leak but made it a «feature» by documenting it.

@Praveen Kumar 2018-02-06 10:43:49

A real time example of memory leak before JDK 1.7

suppose you read a file of 1000 lines of text and keep in String object

String fileText = 1000 characters from file

fileText = fileText.subString(900, fileText.length());

In above code I initially read 1000 char and then did substring to get only 100 last characters. Now fileText should only refer to 100 chars and all other characters should get garbage collected as I lost the reference but before JDK 1.7 substring function indirectly refer to original string of last 100 chars and prevents whole string from garbage collection and whole 1000 chars will be there in memory until you loose reference of substring.

you can create memory leak example like the above

@Karan Khanna 2018-04-19 09:12:27

I don,t think so. A new String is created and returned. Here is a code snippet from open-jdk 6 for subString function return ((beginIndex == 0) && (endIndex == count)) ? this : new String(offset + beginIndex, endIndex - beginIndex, value);

@Praveen Kumar 2018-04-19 09:27:36

correct new string object is getting created but if you see it is passing value which is char array of original string and newly created string keeps the reference of complete char array. you can just compare the implementation from java 6 to 8, java 7 and 8 uses Arrays.copyOfRange(value, offset, offset+count) to return actual substring

@Karan Khanna 2018-04-19 09:38:24

Got it. Thanks.

@Prashant Bhate 2011-07-01 13:33:55

Static field holding object reference [esp final field]

class MemorableClass {
    static final ArrayList list = new ArrayList(100);
}

Calling String.intern() on lengthy String

String str=readString(); // read lengthy string any source db,textbox/jsp etc..
// This will place the string in memory pool from which you can't remove
str.intern();

(Unclosed) open streams ( file , network etc... )

try {
    BufferedReader br = new BufferedReader(new FileReader(inputFile));
    ...
    ...
} catch (Exception e) {
    e.printStacktrace();
}

Unclosed connections

try {
    Connection conn = ConnectionFactory.getConnection();
    ...
    ...
} catch (Exception e) {
    e.printStacktrace();
}

Areas that are unreachable from JVM's garbage collector, such as memory allocated through native methods

In web applications, some objects are stored in application scope until the application is explicitly stopped or removed.

getServletContext().setAttribute("SOME_MAP", map);

Incorrect or inappropriate JVM options, such as the noclassgc option on IBM JDK that prevents unused class garbage collection

See IBM jdk settings.

@Ian McLaird 2011-07-13 04:08:51

I'd disagree that context and session attributes are "leaks." They're just long-lived variables. And the static final field is more or less just a constant. Maybe large constants should be avoided, but I don't think it's fair to call it a memory leak.

@bestsss 2011-07-17 18:38:25

(Unclosed) open streams ( file , network etc... ), doesn't leak for real, during finalization (which will be after the next GC cycle) close() is going to be scheduled (close() is usually not invoked in the finalizer thread since might be a blocking operation). It's a bad practice not to close, but it doesn't cause a leak. Unclosed java.sql.Connection is the same.

@Matt B. 2011-07-22 01:32:24

In most sane JVMs, it appears as though the String class only has a weak reference on its intern hashtable contents. As such, it is garbage collected properly and not a leak. (but IANAJP) mindprod.com/jgloss/interned.html#GC

@Sled 2011-07-22 14:43:53

@Prashant Bade I believe the final 2 examples (i.e. new Boolean and new String) are not memory leaks, but just wastes of memory. Both should end up getting garbage collected eventually and are thus not true leaks.

@Kanagavelu Sugumar 2012-09-10 19:52:57

How Static field holding object reference [esp final field] is a memory leak ??

@Graham 2013-02-10 11:58:46

Reference loops used to be leaks as well. That is where you have instance A referencing instance B, which references instance C, which references instance A, but nothing else references any of those. (The loop may need to be bigger)

@user1050755 2013-03-07 02:12:22

AFAIK this is not true because (as far as I remember) the GC searches for detached sets. But that may depend on the GC in use. @Sugumar: a memory leak is generally just a bug, so a static list of strong references CAN constitute a memory leak if one does not properly handle it.

@Mac 2013-07-27 12:31:39

@bestsss: I couldn't get your point about execution of close() method during next GC cycle..Who calls this method if the application is not calling it? And if finalizer thread is calling it..then is there any official source code for that?

@cHao 2013-08-16 18:54:49

finalize() will be called for open files, sockets, etc. It will call close(). The docs for FileInputStream actually specifically say as much. But the docs are nearly irrelevant here. The entire reason for finalizers is to clean up stuff that would otherwise be leaked, and any class that handles native resources but doesn't implement finalize() is severely broken. Fortunately, java.net and java.io were written by people who know how Java should work. :)

@Not a bug 2014-02-18 10:32:09

Have a look at AutoCloseable, since 1.7

@UrsulRosu 2014-04-11 12:10:00

Memory leaks in garbage-collected languages (more properly known as unintentional object retentions) are insidious. If an object reference is unintentionally retained, not only is that object excluded from garbage collection, but so too are any objects referenced by that object, and so on. Even if only a few object references are unintentionally retained, many, many objects may be prevented from being garbage collected, with potentially large effects on performance.

@Patrick M 2014-08-25 15:37:38

@cHao True. The danger I've run into isn't problems from memory being leaked by Streams. The problem is that not enough memory is leaked by them. You can leak a lot of handles, but still have plenty of memory. The Garbage Collector might then decide not to bother doing a full collection because it still has plenty of memory. This means the finalizer isn't called, so you run out of handles. The problem is that, the finalizers will (usually) be run before you run out of memory from leaking streams, but it might not get called before you run out of something other than memory.

@Patrick M 2014-08-25 15:38:29

@cHao Sadly, this is from personal experience fixing someone else's code.

@cHao 2014-08-25 22:32:44

@PatrickM: Yeah...the big problem with file streams and such isn't the memory -- it's the native handles the JVM had to borrow from the OS to create the stream. They're typically a much more limited resource. With that said, though, it seems like you'd have to be messing with a lot of files, sockets, what-have-you -- and doing very little else -- for it to become a problem. I've personally written code that creates tens of thousands of sockets, streams, etc just to see what would happen. Not much did.

@Patrick M 2014-08-25 23:47:26

@cHao Sure. I think the example I saw was at around 65k different handles to some sort of AWS resource's stream. I agree you need crazy amounts. I was just trying to point out that you might run out of "handles" or whatever before you run out of RAM. Or, you might run out of memory while having plenty of room on the managed heap because the GC doesn't see the real memory pressure the object is creating off the heap.

@Daniel Newtown 2015-06-29 06:39:14

Please have a look at my question, thanks stackoverflow.com/questions/31108772/…

@Sled 2016-02-26 20:50:09

@Graham loops can only cause leaks when using reference counting, but AFAIK java has always used variations of mark-and-sweep where loops die because they can't be reached by any "live" objects.

@Franklin Yu 2016-05-25 04:25:25

@PatrickM, "You can leak a lot of handles, but still have plenty of memory." so it should be called (maybe) "handle leak" instead of "memory leak".

@Patrick M 2016-05-29 17:58:59

@FranklinYu If it's something that only has 2^16 handles, I'd agree, since you're likely to run out of handles without running out of RAM. There was a type of handle that had a max of 2^31 options though. With that one, the system ran out of RAM before you ran out of handles, so I'd call that a "memory leak" caused by a "handle leak".

@Tejas C 2017-03-04 12:27:55

@bestsss we have faced memory issues due to unclosed open streams - causing "Too many open files" error which in turn caused native out of memory error.

@Stefan Reich 2019-01-10 17:48:32

String.intern() is not a memory leak.

@akhambir 2017-11-27 14:51:25

Just like this!

public static void main(String[] args) {
    List<Object> objects = new ArrayList<>();
    while(true) {
        objects.add(new Object());
    }
}

@Karan Khanna 2018-04-19 08:55:39

This is not an example of memory leak. You are just trying to consume the whole memory here with your list. Memory leak is when obsolete references cannot be garbage collected.

@deltamind106 2017-10-13 19:09:24

The interviewer was probably looking for a circular reference like the code below (which incidentally only leak memory in very old JVMs that used reference counting, which isn't the case any more). But it's a pretty vague question, so it's a prime opportunity to show off your understanding of JVM memory management.

class A {
    B bRef;
}

class B {
    A aRef;
}

public class Main {
    public static void main(String args[]) {
        A myA = new A();
        B myB = new B();
        myA.bRef = myB;
        myB.aRef = myA;
        myA=null;
        myB=null;
        /* at this point, there is no access to the myA and myB objects, */
        /* even though both objects still have active references. */
    } /* main */
}

Then you can explain that with reference counting, the above code would leak memory. But most modern JVMs don't use reference counting any longer, most use a sweep garbage collector, which will in fact collect this memory.

Next you might explain creating an Object that has an underlying native resource, like this:

public class Main {
    public static void main(String args[]) {
        Socket s = new Socket(InetAddress.getByName("google.com"),80);
        s=null;
        /* at this point, because you didn't close the socket properly, */
        /* you have a leak of a native descriptor, which uses memory. */
    }
}

Then you can explain this is technically a memory leak, but really the leak is caused by native code in the JVM allocating underlying native resources, which weren't freed by your Java code.

At the end of the day, with a modern JVM, you need to write some Java code that allocates a native resource outside the normal scope of the JVM's awareness.

@user1529891 2017-04-18 16:11:57

A memory leak in java is not your typical C/C++ memory leak.

To understand how the JVM works, read the Understanding Memory Management.

Basically, the important part is:

The Mark and Sweep Model

The JRockit JVM uses the mark and sweep garbage collection model for performing garbage collections of the whole heap. A mark and sweep garbage collection consists of two phases, the mark phase and the sweep phase.

During the mark phase all objects that are reachable from Java threads, native handles and other root sources are marked as alive, as well as the objects that are reachable from these objects and so forth. This process identifies and marks all objects that are still used, and the rest can be considered garbage.

During the sweep phase the heap is traversed to find the gaps between the live objects. These gaps are recorded in a free list and are made available for new object allocation.

The JRockit JVM uses two improved versions of the mark and sweep model. One is mostly concurrent mark and sweep and the other is parallel mark and sweep. You can also mix the two strategies, running for example mostly concurrent mark and parallel sweep.

So, to create a memory leak in Java; the easiest way to do that is to create a database connection, do some work, and simply not Close() it; then generate a new database connection while staying in scope. This isn't hard to do in a loop for example. If you have a worker that pulls from a queue and pushes to a database you can easily create a memory leak by forgetting to Close() connections or opening them when not necessary, and so forth.

Eventually, you'll consume the heap that has been allocated to the JVM by forgetting to Close() the connection. This will result in the JVM garbage collecting like crazy; eventually resulting in java.lang.OutOfMemoryError: Java heap space errors. It should be noted that the error may not mean there is a memory leak; it could just mean you don't have enough memory; databases like Cassandra and ElasticSearch for example can throw that error because they don't have enough heap space.

Its worth noting that this is true for all GC languages. Below, are some examples I've seen working as an SRE:

  • Node using Redis as a queue; the development team created new connections every 12 hours and forgot to close the old ones. Eventually node was OOMd because it consumed all the memory.
  • Golang (I'm guilty of this one); parsing large json files with json.Unmarshal and then passing the results by reference and keeping them open. Eventually, this resulted in the entire heap being consumed by accidental refs I kept open to decode json.

@gurubelli 2017-01-22 19:40:53

From effective java book

  1. whenever a class manages its own memory, the programmer should be alert for memory leaks

.

public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;

public Stack() {
    elements = new Object[DEFAULT_INITIAL_CAPACITY];
}

public void push(Object e) {
    ensureCapacity();
    elements[size++] = e;
}

public Object pop() {
    if (size == 0)
        throw new EmptyStackException();
    return elements[--size];
}

/**
 * Ensure space for at least one more element, roughly doubling the capacity
 * each time the array needs to grow.
 */
private void ensureCapacity() {
    if (elements.length == size)
        elements = Arrays.copyOf(elements, 2 * size + 1);
}

}

Can you spot the memory leak? So where is the memory leak? If a stack grows and then shrinks, the objects that were popped off the stack will not be garbage collected, even if the program using the stack has no more references to them. This is because the stack maintains obsolete references to these objects. An obsolete reference is simply a reference that will never be dereferenced again. In this case, any references outside of the “active portion” of the element array are obsolete. The active portion consists of the elements whose index is less than size.

@kiltek 2018-08-02 07:19:24

Why was this downvoted? It is actually taken from a book.

@0xDEADC0DE 2018-12-27 13:52:26

I think it is downvoted because this example will not create obsolete references. As long as this stack is alive, each reference is accessible through the elements array. Even if size changes every time pop is called, it is still possible to iterate over the complete array using its length property. Therefore there are no obsolete references. I must say that it is usual that a collection releases ownership in a function such as pop though, but this example will not create a memory leak which is the original question

@bestsss 2011-06-30 19:45:13

Below there will be a non-obvious case where Java leaks, besides the standard case of forgotten listeners, static references, bogus/modifiable keys in hashmaps, or just threads stuck without any chance to end their life-cycle.

  • File.deleteOnExit() - always leaks the string, if the string is a substring, the leak is even worse (the underlying char[] is also leaked) - in Java 7 substring also copies the char[], so the later doesn't apply; @Daniel, no needs for votes, though.

I'll concentrate on threads to show the danger of unmanaged threads mostly, don't wish to even touch swing.

  • Runtime.addShutdownHook and not remove... and then even with removeShutdownHook due to a bug in ThreadGroup class regarding unstarted threads it may not get collected, effectively leak the ThreadGroup. JGroup has the leak in GossipRouter.

  • Creating, but not starting, a Thread goes into the same category as above.

  • Creating a thread inherits the ContextClassLoader and AccessControlContext, plus the ThreadGroup and any InheritedThreadLocal, all those references are potential leaks, along with the entire classes loaded by the classloader and all static references, and ja-ja. The effect is especially visible with the entire j.u.c.Executor framework that features a super simple ThreadFactory interface, yet most developers have no clue of the lurking danger. Also a lot of libraries do start threads upon request (way too many industry popular libraries).

  • ThreadLocal caches; those are evil in many cases. I am sure everyone has seen quite a bit of simple caches based on ThreadLocal, well the bad news: if the thread keeps going more than expected the life the context ClassLoader, it is a pure nice little leak. Do not use ThreadLocal caches unless really needed.

  • Calling ThreadGroup.destroy() when the ThreadGroup has no threads itself, but it still keeps child ThreadGroups. A bad leak that will prevent the ThreadGroup to remove from its parent, but all the children become un-enumerateable.

  • Using WeakHashMap and the value (in)directly references the key. This is a hard one to find without a heap dump. That applies to all extended Weak/SoftReference that might keep a hard reference back to the guarded object.

  • Using java.net.URL with the HTTP(S) protocol and loading the resource from(!). This one is special, the KeepAliveCache creates a new thread in the system ThreadGroup which leaks the current thread's context classloader. The thread is created upon the first request when no alive thread exists, so either you may get lucky or just leak. The leak is already fixed in Java 7 and the code that creates thread properly removes the context classloader. There are few more cases (like ImageFetcher, also fixed) of creating similar threads.

  • Using InflaterInputStream passing new java.util.zip.Inflater() in the constructor (PNGImageDecoder for instance) and not calling end() of the inflater. Well, if you pass in the constructor with just new, no chance... And yes, calling close() on the stream does not close the inflater if it's manually passed as constructor parameter. This is not a true leak since it'd be released by the finalizer... when it deems it necessary. Till that moment it eats native memory so badly it can cause Linux oom_killer to kill the process with impunity. The main issue is that finalization in Java is very unreliable and G1 made it worse till 7.0.2. Moral of the story: release native resources as soon as you can; the finalizer is just too poor.

  • The same case with java.util.zip.Deflater. This one is far worse since Deflater is memory hungry in Java, i.e. always uses 15 bits (max) and 8 memory levels (9 is max) allocating several hundreds KB of native memory. Fortunately, Deflater is not widely used and to my knowledge JDK contains no misuses. Always call end() if you manually create a Deflater or Inflater. The best part of the last two: you can't find them via normal profiling tools available.

(I can add some more time wasters I have encountered upon request.)

Good luck and stay safe; leaks are evil!

@leonbloy 2011-07-09 01:54:40

Creating but not starting a Thread... Yikes, I was badly bitten by this one some centuries ago! (Java 1.3)

@bestsss 2011-07-09 06:52:08

@leonbloy, before it was even worse as the thread was added straight to the threadgroup, not starting meant very hard leak. Not it just increases the unstarted count but that prevents the thread group from destroying (lesser evil but still a leak)

@Lawrence Dol 2017-11-08 02:47:03

Thank you! "Calling ThreadGroup.destroy() when the ThreadGroup has no threads itself..." is an incredibly subtle bug; I've been chasing this for hours, led astray because enumerating the thread in my control GUI showed nothing, but the thread group and, presumably, at least one child group would not go away.

@Lawrence Dol 2017-11-09 21:09:34

@bestsss : I'm curious, why would you want to remove a shutdown hook, given that it runs at, well, JVM shutdown?

@Ron 2011-06-30 08:39:19

I have had a nice "memory leak" in relation to PermGen and XML parsing once. The XML parser we used (I can't remember which one it was) did a String.intern() on tag names, to make comparison faster. One of our customers had the great idea to store data values not in XML attributes or text, but as tagnames, so we had a document like:

<data>
   <1>bla</1>
   <2>foo</>
   ...
</data>

In fact, they did not use numbers but longer textual IDs (around 20 characters), which were unique and came in at a rate of 10-15 million a day. That makes 200 MB of rubbish a day, which is never needed again, and never GCed (since it is in PermGen). We had permgen set to 512 MB, so it took around two days for the out-of-memory exception (OOME) to arrive...

@Paŭlo Ebermann 2011-07-03 00:18:34

Just to nitpick your example code: I think numbers (or strings starting with numbers) are not allowed as element names in XML.

@jmiserez 2017-04-18 19:47:08

Note that this is no longer true for JDK 7+, where String interning happens on the heap. See this article for a detailed writeup: java-performance.info/string-intern-in-java-6-7-8

@pillingworth 2011-06-28 13:47:23

A common example of this in GUI code is when creating a widget/component and adding a listener to some static/application scoped object and then not removing the listener when the widget is destroyed. Not only do you get a memory leak, but also a performance hit as when whatever you are listening to fires events, all your old listeners are called too.

@rds 2011-07-22 16:34:12

The android platform gives the exemple of a memory leak created by caching a Bitmap in the static field of a View.

@Vineet Reynolds 2011-06-24 16:21:58

The following is a pretty pointless example, if you do not understand JDBC. Or at least how JDBC expects a developer to close Connection, Statement and ResultSet instances before discarding them or losing references to them, instead of relying on the implementation of finalize.

void doWork()
{
   try
   {
       Connection conn = ConnectionFactory.getConnection();
       PreparedStatement stmt = conn.preparedStatement("some query"); // executes a valid query
       ResultSet rs = stmt.executeQuery();
       while(rs.hasNext())
       {
          ... process the result set
       }
   }
   catch(SQLException sqlEx)
   {
       log(sqlEx);
   }
}

The problem with the above is that the Connection object is not closed, and hence the physical connection will remain open, until the garbage collector comes around and sees that it is unreachable. GC will invoke the finalize method, but there are JDBC drivers that do not implement the finalize, at least not in the same way that Connection.close is implemented. The resulting behavior is that while memory will be reclaimed due to unreachable objects being collected, resources (including memory) associated with the Connection object might simply not be reclaimed.

In such an event where the Connection's finalize method does not clean up everything, one might actually find that the physical connection to the database server will last several garbage collection cycles, until the database server eventually figures out that the connection is not alive (if it does), and should be closed.

Even if the JDBC driver were to implement finalize, it is possible for exceptions to be thrown during finalization. The resulting behavior is that any memory associated with the now "dormant" object will not be reclaimed, as finalize is guaranteed to be invoked only once.

The above scenario of encountering exceptions during object finalization is related to another other scenario that could possibly lead to a memory leak - object resurrection. Object resurrection is often done intentionally by creating a strong reference to the object from being finalized, from another object. When object resurrection is misused it will lead to a memory leak in combination with other sources of memory leaks.

There are plenty more examples that you can conjure up - like

  • Managing a List instance where you are only adding to the list and not deleting from it (although you should be getting rid of elements you no longer need), or
  • Opening Sockets or Files, but not closing them when they are no longer needed (similar to the above example involving the Connection class).
  • Not unloading Singletons when bringing down a Java EE application. Apparently, the Classloader that loaded the singleton class will retain a reference to the class, and hence the singleton instance will never be collected. When a new instance of the application is deployed, a new class loader is usually created, and the former class loader will continue to exist due to the singleton.

@Hardwareguy 2011-07-21 16:23:36

You will reach maximum open connection limit before you hit memory limits usually. Don't ask me why I know...

@chotchki 2013-08-20 16:06:38

The Oracle JDBC driver is notorious for doing this.

@Michael Shopsin 2014-04-22 14:46:58

@Hardwareguy I hit the connection limits of the SQL databases a lot until I put Connection.close into the finally block of all my SQL calls. For extra fun I called some long running Oracle stored procedures that required locks on the Java side to prevent too many calls to the database.

@Aseem Bansal 2014-09-22 18:21:03

@Hardwareguy That is interesting but it is not really necessary that actual connection limits will be hit for all environments. For instance, for an application deployed on weblogic app server 11g I have seen connection leakages at a large scale. But due to a option of harvesting leaked connections database connections remained available while memory leaks were being introduced. I am not sure about all environments.

@Bjørn Stenfeldt 2017-08-31 08:07:33

In my experience you get a memory leak even if you close the connection. You need to close the ResultSet and PreparedStatement first. Had a server that crashed repeatedly after hours or even days of working fine, due to OutOfMemoryErrors, until I started doing that.

@zero_yu 2018-02-24 22:55:22

Sorry, I am new to Java, so my question may look stupid. Could you please explain "The resulting behavior is that while memory will be reclaimed due to unreachable objects being collected, resources (including memory) associated with the Connection object might simply not be reclaimed"? Do you mean that the memory allocated for the connection object itself will be reclaimed, however, the memory allocated for the resources related to the connection object won't be reclaimed? What exactly do the resources mean? Thanks!

@yankee 2011-07-02 10:23:36

I can copy my answer from here: Easiest way to cause memory leak in Java?

"A memory leak, in computer science (or leakage, in this context), occurs when a computer program consumes memory but is unable to release it back to the operating system." (Wikipedia)

The easy answer is: You can't. Java does automatic memory management and will free resources that are not needed for you. You can't stop this from happening. It will ALWAYS be able to release the resources. In programs with manual memory management, this is different. You cann get some memory in C using malloc(). To free the memory, you need the pointer that malloc returned and call free() on it. But if you don't have the pointer anymore (overwritten, or lifetime exceeded), then you are unfortunately incapable of freeing this memory and thus you have a memory leak.

All the other answers so far are in my definition not really memory leaks. They all aim at filling the memory with pointless stuff real fast. But at any time you could still dereference the objects you created and thus freeing the memory --> NO LEAK. acconrad's answer comes pretty close though as I have to admit since his solution is effectively to just "crash" the garbage collector by forcing it in an endless loop).

The long answer is: You can get a memory leak by writing a library for Java using the JNI, which can have manual memory management and thus have memory leaks. If you call this library, your java process will leak memory. Or, you can have bugs in the JVM, so that the JVM looses memory. There are probably bugs in the JVM, there may even be some known ones since garbage collection is not that trivial, but then it's still a bug. By design this is not possible. You may be asking for some java code that is effected by such a bug. Sorry I don't know one and it might well not be a bug anymore in the next Java version anyway.

@Mason Wheeler 2014-01-23 19:54:30

That's an extremely limited (and not very useful) definition of memory leaks. The only definition that makes sense for practical purposes is "a memory leak is any condition in which the program continues to hold memory allocated after the data it holds it is no longer needed."

@Tomáš Zato - Reinstate Monica 2016-01-05 08:36:40

The mentioned acconrad's answer was deleted?

@yankee 2016-01-05 11:14:26

@TomášZato: No it's not. I turned the reference above to link now, so you can easily find it.

@autistic 2016-12-06 17:08:05

What is object resurrection? How many times does a destructor get called? How do these questions disprove this answer?

@toolforger 2018-11-03 23:37:28

Well, sure you can create a memory leak inside Java, despite GC, and still fulfill the above definition. Just have an append-only data structure, protected against external access so that no other code every removes it - the program cannot release the memory because it does not have the code.

@stemm 2011-07-11 12:55:59

You are able to make memory leak with sun.misc.Unsafe class. In fact this service class is used in different standard classes (for example in java.nio classes). You can't create instance of this class directly, but you may use reflection to do that.

Code doesn't compile in Eclipse IDE - compile it using command javac (during compilation you'll get warnings)

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import sun.misc.Unsafe;


public class TestUnsafe {

    public static void main(String[] args) throws Exception{
        Class unsafeClass = Class.forName("sun.misc.Unsafe");
        Field f = unsafeClass.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe unsafe = (Unsafe) f.get(null);
        System.out.print("4..3..2..1...");
        try
        {
            for(;;)
                unsafe.allocateMemory(1024*1024);
        } catch(Error e) {
            System.out.println("Boom :)");
            e.printStackTrace();
        }
    }

}

@stemm 2011-07-11 15:32:15

Allocated memory is invisible for garbage collector

@bestsss 2011-07-17 18:35:11

The allocated memory doesn't belong to Java either.

@Berlin Brown 2011-07-21 16:40:44

Is this sun/oracle jvm specific? E.g. will this work on IBM?

@stemm 2011-07-22 13:50:09

@Berlin Brow In fact I've didn't work with jvm of IBM. But as I told - some standart packages (java.nio, java.util.concurrent etc.) use this service class. So if IBMs jvm supports usage of these libraries, probably it has native code to cope with sun.misc.Unsafe

@Michael Anderson 2016-06-02 03:19:19

The memory certainly does "belong to Java", at least in the sense that i) its not available to anyone else, ii) when the Java application exits it will be returned to the system. It is just outside the JVM.

@Michael Anderson 2016-06-02 03:21:13

This will build in eclipse (at least in recent versions) but you'll need to change the compiler settings: in Window > Preferences > Java > Compiler > Errors/Warning > Deprecated and restricted API set Forbidden reference (access rules) to "Warning".

@Darrell Teague 2018-04-03 18:58:18

Strongly advise readers to consider that IDE specific behaviors in developing code is not only irrelevant but dangerous. Namely, system stability and consistency demands a singular, consistent compiler. An IDE generally uses "javac" of some version from some vendor/impl. Consistency in runtime behavior within a given JVM relies on having the same byte-code interpretation. Since servers do not run IDEs or their (as likely instrumented) run-time environments, it is dangerous to make any presumptions or cases around what a given IDE does or doesn't do. Reference the javac instance and JVM only.

@meriton - on strike 2011-06-24 21:28:37

Probably one of the simplest examples of a potential memory leak, and how to avoid it, is the implementation of ArrayList.remove(int):

public E remove(int index) {
    RangeCheck(index);

    modCount++;
    E oldValue = (E) elementData[index];

    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index + 1, elementData, index,
                numMoved);
    elementData[--size] = null; // (!) Let gc do its work

    return oldValue;
}

If you were implementing it yourself, would you have thought to clear the array element that is no longer used (elementData[--size] = null)? That reference might keep a huge object alive ...

@rds 2011-07-22 16:26:40

And where is the memory leak here?

@meriton - on strike 2011-07-23 13:26:32

@maniek: I did not mean to imply that this code exhibits a memory leak. I quoted to it to show that sometimes non-obvious code is required to avoid accidental object retention.

@Koray Tugay 2014-06-09 18:36:22

What is RangeCheck(index); ?

@rents 2015-06-27 02:22:14

Joshua Bloch gave this example in Effective Java showing a simple implementation of Stacks. A very good answer.

@TV Trailers 2015-03-11 14:38:07

There's no such thing as a memory leak in Java. Memory leak is a phrase borrowed from C et al. Java deals with memory allocation internally with the help of the GC. There's memory wastefulness (ie. leaving stranded objects), but not memory leak.

@bvdb 2014-07-18 19:24:36

What's a memory leak:

  • It's caused by a bug or bad design.
  • It's a waste of memory.
  • It gets worse over time.
  • The garbage collector cannot clean it.

Typical example:

A cache of objects is a good starting point to mess things up.

private static final Map<String, Info> myCache = new HashMap<>();

public void getInfo(String key)
{
    // uses cache
    Info info = myCache.get(key);
    if (info != null) return info;

    // if it's not in cache, then fetch it from the database
    info = Database.fetch(key);
    if (info == null) return null;

    // and store it in the cache
    myCache.put(key, info);
    return info;
}

Your cache grows and grows. And pretty soon the entire database gets sucked into memory. A better design uses an LRUMap (Only keeps recently used objects in cache).

Sure, you can make things a lot more complicated:

  • using ThreadLocal constructions.
  • adding more complex reference trees.
  • or leaks caused by 3rd party libraries.

What often happens:

If this Info object has references to other objects, which again have references to other objects. In a way you could also consider this to be some kind of memory leak, (caused by bad design).

@Jaskey 2014-08-19 03:20:21

Carelessly Using a non-static inner Class inside a class who has its own life cycle.

In Java, non-static inner and anonymous classes hold an implicit reference to their outer class. Static inner classes, on the other hand, do not.

Here is a common example to have memory leak in Android,which is not obvious though:

public class SampleActivity extends Activity {

  private final Handler mLeakyHandler = new Handler() { //non-static inner class, holds the reference to the SampleActivity outter class
    @Override
    public void handleMessage(Message msg) {
      // ...
    }
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Post a message and delay its execution for a long time.
    mLeakyHandler.postDelayed(new Runnable() {//here, the anonymous inner class holds the reference to the SampleActivity class too
      @Override
      public void run() {
     //.... 
      }
    }, SOME_TOME_TIME);

    // Go back to the previous Activity.
    finish();
  }}

This will prevent the activity context from being garbage collected.

@ban-geoengineering 2015-06-24 13:08:31

Would making mLeakyHandler static prevent it from leaking memory? And are there any (other) ways to prevent mLeakyHandler from leaking the activity? Also, how would you go about solving the same problem for the anonymous Runnable inner class?

@Jaskey 2015-06-25 02:20:16

@ban-geoengineering Yes, make it static and if you need to involve the outter activity, make the handler to hold a WeakReference to the activity, please check androiddesignpatterns.com/2013/01/…

@Viraj 2014-06-18 11:53:14

String.substring method in java 1.6 create a memory leak. This blog post explains it.

http://javarevisited.blogspot.com/2011/10/how-substring-in-java-works.html

@Alexandre Santos 2014-06-05 21:54:41

There are many answers on how to create a memory leak in Java, but please note the point asked during the interview.

"how to create a memory leak with Java?" is an open-ended question, whose purpose is to evaluate the degree of experience a developer has.

If I ask you "Do you have experience troubleshooting memory leaks in Java?", your answer would be a simple "Yes". I would have then to follow up with "Could you give me examples where you hat to troubleshoot memory leaks?", to which you would give me one or two examples.

However, when the interviewer asks "how to create a memory leak with Java?" the expected answer should follow alongs these lines:

  • I've encountered a memory leak ... (say when) [that shows me experience]
  • The code that was causing it was... (explain code) [you fixed it yourself]
  • The fix I applied was based on ... (explain fix) [this gives me a chance to ask specifics about the fix]
  • The test I did was ... [gives me the chance of asking other testing methodologies]
  • I documented it this way ... [extra points. Good if you documented it]
  • So, it is reasonable to think that, if we follow this in reverse order, which is, get the code I fixed, and remove my fix, that we would have a memory leak.

When the developer fails to follow this line of thought I try to guide him/her asking "Could you give me an example of how could Java leak memory?", followed by "Did you ever have to fix any memory leak in Java?"

Note that I am not asking for an example on how to leak memory in Java. That would be silly. Who would be interested in a developer who can effectively write code that leaks memory?

@Stefano Sanfilippo 2015-06-21 16:40:48

Regarding the last sentence, the best way to win over the evil is knowing it well. If you want to write a secure web application, you should make yourself familiar with the most common exploit techniques and vulnerabilities, like SQL injections or buffer overflows. Similarly, if you want to write leak-free code, you should at least be able to describe the most common ways of leaking memory, like lost pointers in C/C++. Definitely less straightforward in Java, though.

@Puneet 2011-07-21 19:39:32

I recently encountered a memory leak situation caused in a way by log4j.

Log4j has this mechanism called Nested Diagnostic Context(NDC) which is an instrument to distinguish interleaved log output from different sources. The granularity at which NDC works is threads, so it distinguishes log outputs from different threads separately.

In order to store thread specific tags, log4j's NDC class uses a Hashtable which is keyed by the Thread object itself (as opposed to say the thread id), and thus till the NDC tag stays in memory all the objects that hang off of the thread object also stay in memory. In our web application we use NDC to tag logoutputs with a request id to distinguish logs from a single request separately. The container that associates the NDC tag with a thread, also removes it while returning the response from a request. The problem occurred when during the course of processing a request, a child thread was spawned, something like the following code:

pubclic class RequestProcessor {
    private static final Logger logger = Logger.getLogger(RequestProcessor.class);
    public void doSomething()  {
        ....
        final List<String> hugeList = new ArrayList<String>(10000);
        new Thread() {
           public void run() {
               logger.info("Child thread spawned")
               for(String s:hugeList) {
                   ....
               }
           }
        }.start();
    }
}    

So an NDC context was associated with inline thread that was spawned. The thread object that was the key for this NDC context, is the inline thread which has the hugeList object hanging off of it. Hence even after the thread finished doing what it was doing, the reference to the hugeList was kept alive by the NDC context Hastable, thus causing a memory leak.

@TraderJoeChicago 2011-09-20 23:10:42

That sucks. You should check this logging library that allocates ZERO memory while logging to a file: mentalog.soliveirajr.com

@sparc_spread 2014-07-02 21:40:49

+1 Do you know offhand whether there is a similar issue with the MDC in slf4j/logback (successor products by the same author)? I'm about to do a deep dive on the source but wanted to check first. Either way, thanks for posting this.

@h22 2014-01-07 12:56:37

A thread that does not terminate (say sleeps indefinitely in its run method). It will not be garbage collected even if we loose a reference to it. You can add fields to make the thread object is a big as you want.

The currently top answer lists more tricks around this but these seem redundant.

@Boann 2013-08-31 05:10:27

Threads are not collected until they terminate. They serve as roots of garbage collection. They are one of the few objects that won't be reclaimed simply by forgetting about them or clearing references to them.

Consider: the basic pattern to terminate a worker thread is to set some condition variable seen by the thread. The thread can check the variable periodically and use that as a signal to terminate. If the variable is not declared volatile, then the change to the variable might not be seen by the thread, so it won't know to terminate. Or imagine if some threads want to update a shared object, but deadlock while trying to lock on it.

If you only have a handful of threads these bugs will probably be obvious because your program will stop working properly. If you have a thread pool that creates more threads as needed, then the obsolete/stuck threads might not be noticed, and will accumulate indefinitely, causing a memory leak. Threads are likely to use other data in your application, so will also prevent anything they directly reference from ever being collected.

As a toy example:

static void leakMe(final Object object) {
    new Thread() {
        public void run() {
            Object o = object;
            for (;;) {
                try {
                    sleep(Long.MAX_VALUE);
                } catch (InterruptedException e) {}
            }
        }
    }.start();
}

Call System.gc() all you like, but the object passed to leakMe will never die.

(*edited*)

@Spidey 2013-09-26 22:33:50

It's not leaked, the code is stuck but it's still in scope.

@Boann 2013-09-26 23:39:39

@Spidey Nothing is "stuck". The calling method returns promptly, and the passed object will never be reclaimed. That's precisely a leak.

@Spidey 2013-09-27 01:24:42

You'll have a thread "running" (or sleeping, whatever) for the lifetime of your program. That doesn't count as a leak to me. As well as a pool doesn't count as a leak, even if you don't use it entirely.

@Boann 2013-09-27 01:39:58

@Spidey "You'll have a [thing] for the lifetime of your program. That doesn't count as a leak to me." Do you hear yourself?

@Spidey 2013-09-27 15:51:10

Yes I do. The process still references the thread, and the thread still references the o object. You may have misunderstood what a memory leak is.

@Boann 2013-09-27 18:00:38

@Spidey If you would count memory that the process knows about as not being leaked, then all the answers here are wrong, since the process always tracks which pages in its virtual address space are mapped. When the process terminates, the OS cleans up all the leaks by putting the pages back on the free page stack. To take that to the next extreme, one could beat to death any argued leak by pointing out that none of the physical bits in the RAM chips or in the swap space on disk have been physically misplaced or destroyed, so you can switch the computer off and on again to clean up any leak.

@Boann 2013-09-27 18:00:58

The practical definition of a leak is that it's memory which has been lost track of such that we don't know and thus can't perform the procedure necessary to reclaim only it; we would have to tear down and rebuild the entire memory space. A rogue thread like this could arise naturally through a deadlock or dodgy threadpool implementation. Objects referenced by such threads, even indirectly, are now prevented from ever being collected, so we have memory which will not be naturally reclaimed or reusable during the lifetime of the program. I'd call that a problem; specifically it's a memory leak.

@Boann 2013-10-01 18:17:44

@Spidey What is your answer? What do you consider a leak?

@Spidey 2013-10-02 14:06:58

Since Java has a garbage collector, I don't think it can even leak.

@Boann 2013-10-02 14:22:45

@Spidey Then try it for yourself and you'll see that it does leak. The garbage collector isn't (and cannot be) infallible because it can't tell the difference between live references and obsolete ones, which is why explicit nulling of obsolete references is necessary when the object or scope holding the obsolete reference is still in use.

@Spidey 2013-10-02 18:07:15

There is no difference between "live references and obsolete ones" in the context of the question. They are still referenced somewhere. In a C program, a leak isn't referenced anywhere, even the OS can't touch it. It can release all memory pages used by a given process, but it can't reference each and every memory block allocated.

@Boann 2013-10-02 19:36:44

@Spidey It's the most important difference. At a lower level (program -> JVM -> OS -> RAM chips -> Universe) any memory leak from the higher level becomes unreal. The practical definition for a memory leak is that during execution, your memory space (at whatever level you define it) is accumulating things which are not wanted, reducing available space for things which are wanted. "In a C program, a leak isn't referenced anywhere" -- also wrong -- leaked memory could still be referenced. What matters is whether the memory can be re-used, which in C does not depend on whether it's referenced.

@Spidey 2013-10-02 23:19:58

obviously not much people think you are right. See this: ibm.com/developerworks/rational/library/05/0816_GuptaPalanki Memory leaks in Java are not real leaks, they are bad design choices or bugs in code.

@Boann 2013-10-03 16:14:50

@Spidey "not much people think you are right".. Uh, about which? Which people? Where? Check the previous page of answers for the many older, popular answers that I'm defending here and which you are calling wrong. "Memory leaks in Java are not real leaks" Nowhere does the article say that. It gives examples of memory leaks and shows how they are a real loss of usable memory due to objects not being reclaimed. Those objects accumulate over time and become a real problem. That's what a memory leak is. "they are bad design choices or bugs in code" ... which result in memory leaks, yes.

@Spidey 2013-10-03 17:23:57

I mean all the people who read your answer and our discussion, and still didn't care to up or down your post. But that's not a real argument anyway. See slowlyLeakingVector in Listing 2. I could accept that as a memory leak, but that's different from what you are doing. As I see, your answer suggests that any unused allocated object implies in a leak. I don't agree with that.

@Bill K 2013-10-03 22:02:04

This is totally valid code, it's what it means to use threads. They are designed to keep their references. Also it's not only threads that do this, also GUI frames keep everything referenced by them even though there is no thread. There are a few other "tops" to the GC tree as well. If you have a thread that runs forever then, by design, it will keep everything it references forever, otherwise nothing will work. If this is not what you intended however, then you DO have a programming bug!

@Boann 2013-10-04 04:30:14

@Spidey "I could accept that as a memory leak" Thank you. Earlier, you'd said something couldn't be a leak if it's still referenced and that you couldn't have a leak in Java because it has a garbage collector. >_< "Your answer suggests that any unused allocated object implies a leak". Well, the example is a scenario of an object that the garbage collector can't/won't collect. If it emerges in a program and happens repeatedly it becomes a leak. I'll try to improve my answer with that info.

@Evan Plaice 2014-02-24 10:08:41

Can't you just allocate a bunch of memory on background threads and intentionally deadlock them by using a very poorly structured system of nested thread locks? It fits the profile of running for the life of the program and not being accessible by the application or recoverable by the GC.

@Basanth Roy 2013-08-29 12:10:39

Throw an unhandled exception from the finalize method.

@Tarik 2013-07-09 06:45:21

Lapsed Listerners is a good example of memory leaks: Object is added as a Listener. All references to the object are nulled when the object is not needed anymore. However, forgetting to remove the object from the Listener list keeps the object alive and even responding to events, thereby wasting both memory and CPU. See http://www.drdobbs.com/jvm/java-qa/184404011

Related Questions

Sponsored Content

58 Answered Questions

[SOLVED] How do I read / convert an InputStream into a String in Java?

28 Answered Questions

34 Answered Questions

[SOLVED] Create ArrayList from array

65 Answered Questions

[SOLVED] How do I generate random integers within a specific range in Java?

  • 2008-12-12 18:20:57
  • user42155
  • 3922740 View
  • 3382 Score
  • 65 Answer
  • Tags:   java random integer

86 Answered Questions

[SOLVED] Is Java "pass-by-reference" or "pass-by-value"?

42 Answered Questions

[SOLVED] How do I convert a String to an int in Java?

41 Answered Questions

[SOLVED] How do I efficiently iterate over each entry in a Java Map?

32 Answered Questions

[SOLVED] When to use LinkedList over ArrayList in Java?

26 Answered Questions

[SOLVED] How to get an enum value from a string value in Java?

  • 2009-03-02 22:56:34
  • Malachi
  • 1067523 View
  • 1896 Score
  • 26 Answer
  • Tags:   java enums

Sponsored Content