Memory leak traps in the Java Standard API
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.
Solution 1:
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:
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.