Memory leak traps in the Java Standard API

JavaApiMemory Leaks

Java Problem Overview


What classes of the Java Standard API can cause memory leaks when used in an (not obviously) incorrect way? And how can these memory leaks be avoided/fixed?

Example: ObjectInputStream and ObjectOutputStream keep references to all objects they have seen in order to send subsequent occurences of the same object as references rather than copies (and thereby deal with circular references). This causes a memory leak when you keep such a stream open indefinitely (e.g. when using it to communicate over the network).

Fix: Call reset() periodically or after each top-level object.

Java Solutions


Solution 1 - Java

A big one is that getting substrings of Java strings refers to the original string.

Example: you read in a 3000 character record and get a substring of 12 characters, returning that to the caller (within the same JVM). Even though you don't directly have a reference to the original string, that 12 character string is still using 3000 characters in memory.

For systems that receive and then parse lots of messages, this can be a real problem.

You have a couple of ways to avoid this:

String sub = new String(str.substring(6,12));

or

String sub = str.substring(6,12).intern();

The first is more clearcut. The second has other implications because you're using PermGen space. Overused you could run out unless you give your VM enough.

Remember this is only relevant if you're taking small substrings and then throwing away the original string and you're doing this a lot.

Solution 2 - Java

Everything you register as the recipient of an Event, e.g. in GUI frameworks, cannot be garbage collected as long as it is registered and the event source is alive.

This may introduce memory leaks, if a developer is not aware of that strong reference from the event source to the event subscriber.

Solution 3 - Java

Any non-static inner classes you make hold on to outer classes. So that innocent-looking inner class can hold onto a huge object graph. Put the instance in a static or application-wide collection somewhere and you're using a lot of memory you're not supposed to be using.

Solution 4 - Java

Each instantiation of a Thread allocates memory for a stack (default 512k, tuneable via -Xss). It's not a leak as such, but a naive attempt to heavily multi-thread an application will result in a sizable non-obvious consumption of memory.

Solution 5 - Java

Any class with dispose() method?

For example java.awt.Window#dispose:

> public void dispose() > > Releases all of the native screen resources used by this Window, its subcomponents, and all of its owned children. That is, the resources for these Components will be destroyed, any memory they consume will be returned to the OS, and they will be marked as undisplayable.

Solution 6 - Java

Usage of strong references when weak references would have been sufficient. Application and APIs that perform their own state and resource management are the usual culprits here.

Then, there is the usage of the Observer pattern, which could lead to memory leaks - when the Observer delists itself from the Subject, memory cannot be reclaimed unless the Subject also releases the reference to the Observer/Listener. This has already been pointed out earlier, but not many people realise that even loggers are observers.

Additionally, there is the likelihood of classes, whose objects when instantiated are automatically placed into a static member. Some of these classes do not even have a release() or a dispose() method so the references continue to be held by the static member. This variety of memory leaks eventually results in a OutOfMemory error with a PermGen space issue reported as the root cause, making it more difficult to diagnose.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMichael BorgwardtView Question on Stackoverflow
Solution 1 - JavacletusView Answer on Stackoverflow
Solution 2 - JavaBlackView Answer on Stackoverflow
Solution 3 - JavakrosenvoldView Answer on Stackoverflow
Solution 4 - JavaBrian AgnewView Answer on Stackoverflow
Solution 5 - JavadfaView Answer on Stackoverflow
Solution 6 - JavaVineet ReynoldsView Answer on Stackoverflow