Here's a great way to build a true memory leak (objects inaccessible by running code yet furthermore stored in memory) in real Java:
- The application performs a long-running thread (or use a thread supply to leak even quicker).
- The thread stores a class via an (optionally custom) ClassLoader.
- The class designates a large part of memory (e.g. new byte[1000000]), reserves a piece of strong evidence 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 get the leak work that much quicker.
- The thread clears all references to the system class or the ClassLoader it was loaded from.
- Repeat.
This serves because the ThreadLocal keeps a reference to the object, which holds a reference to its Class, which in turn holds a reference to its ClassLoader. The ClassLoader, in turn, retains a reference to all the Classes it has placed.
(It was more serious in many JVM implementations, particularly before Java 7, because Classes and ClassLoaders were designated straight into permgen and were nevermore GC'd at all. However, despite of how the JVM works class unloading, a ThreadLocal will still prevent a Class object from being developed.)
A change on this pattern is why application packages (like Tomcat) can flow memory like a sieve if you often redeploy applications that appear to use ThreadLocals in any way. (For the application container uses Threads as defined, and each moment you redeploy the application a new ClassLoader is practiced.)
here are some example code that shows this behavior in action.