Trap #1: Static Collection Memory Leaks in the Heap
Adding objects to a public static List or static Map creates GC roots that persist for the lifetime of the JVM process. Because the GC only collects unreferenced objects, static collections continually grow, eventually triggering fatal OutOfMemoryError: Java heap space.
Every executing thread has an isolated call stack (default 1MB). Deep recursion without a base case or circular object references quickly fills the stack frames, immediately throwing a StackOverflowError that crashes the executing thread.
Trap #3: Metaspace Memory Leaks from Dynamic Classloading
Classes, method metadata, and constant pools reside off-heap in native memory called Metaspace. Creating dynamic proxies, bytecode generation, or uncollected custom ClassLoaders without releasing class references triggers fatal OutOfMemoryError: Metaspace.
Trap #4: Blindly Adjusting -Xmx Without Analyzing Heap Dumps
Increasing maximum heap size (-Xmx8g) to fix an out-of-memory error without analyzing heap dumps (.hprof) via VisualVM or Eclipse MAT merely delays the crash while prolonging Garbage Collection pause times.
Trap #5: The Zombie Object Finalizer Hazard
Overriding finalize() delays object reclamation by at least two GC cycles, can resurrect dead objects into active heap references, and causes severe throughput degradation. The finalizer mechanism is deprecated; use AutoCloseable with try-with-resources.
💬 Frequently Asked Questions
What is stored on the Java Stack versus the Java Heap?
The Stack stores executing method frames, local primitive variables, and object reference pointers. It is fast and automatically cleaned as methods return. The Heap stores all instantiated objects and arrays; it is managed by the Garbage Collector.
Is Java pass-by-value or pass-by-reference?
Java is strictly pass-by-value 100% of the time. When passing an object to a method, Java copies the value of the reference pointer, not the object itself. Reassigning the parameter variable inside the method does not affect the caller's reference.
How does the Garbage Collector know when an object can be deleted?
The GC performs root reachability analysis starting from GC Roots (active thread stacks, static variables, JNI references). Any object on the heap that cannot be reached through a reference chain from a GC root is marked for garbage collection.
What is the difference between Young Generation and Old Generation memory?
The JVM heap is divided into Young Gen (Eden, Survivor spaces) where new objects are created, and Old Gen where long-lived objects survive. Most objects die young (Weak Generational Hypothesis), so Minor GCs run quickly on Young Gen without scanning Old Gen.
How does try-with-resources prevent resource and memory leaks?
Classes implementing java.lang.AutoCloseable used in a try(...) statement automatically have their close() method invoked when exiting the block, guaranteeing file descriptors, database connections, and native sockets are freed even during exceptions.