JVM, Memory and Garbage Collection in Java Explained
Understand how Java runs under the hood — the JVM and bytecode, stack vs heap memory, and how garbage collection automatically frees objects. The final Core Java lesson.
Congratulations — you've reached the final lesson of the Core Java phase! We'll finish by lifting the hood to understand what actually happens when your Java code runs: the JVM, how memory is organised into the stack and heap, and how garbage collection quietly cleans up after you. You don't need to memorise this, but understanding it will make you a noticeably more confident developer — and it ties together concepts from the whole course.
The JVM: Java's superpower
Back in Lesson 1 you learned Java's motto: "write once, run anywhere." The JVM (Java Virtual Machine) is what makes that true. Your .java code is compiled into platform-independent bytecode (.class files), and the JVM — a program installed on each operating system — runs that bytecode. So the same compiled Java runs on Windows, Mac, and Linux, because each has its own JVM translating bytecode to that machine.
Your code (Main.java)
│ javac compiles
▼
Bytecode (Main.class) ← platform-independent
│ the JVM runs it
▼
Runs on Windows / Mac / Linux
How memory is organised: stack vs heap
When your program runs, the JVM splits memory into two main areas. Understanding the difference finally explains a lot of earlier behaviour:
- Stack — stores method calls and local variables (primitives like
int x = 5, and references to objects). It's fast and cleaned up automatically as each method finishes. - Heap — stores every object you create with
new. Objects live here until nothing references them anymore.
So when you write Car c = new Car();, the Car object sits in the heap, and the variable c (a reference pointing to it) sits in the stack. This also explains, from Lesson 25, why == compares references — it's comparing the stack pointers, not the heap contents.
Garbage collection: automatic cleanup
Here's one of Java's greatest conveniences. In some languages you must manually free memory when done with an object — forget, and you get memory leaks; do it wrong, and you get crashes. Java handles this for you with the Garbage Collector (GC).
The rule is simple: once no references point to an object, it becomes eligible for garbage collection, and the JVM automatically reclaims its memory in the background.
Car c = new Car(); // object created on the heap c = null; // nothing points to the Car now // → the Car is now eligible for garbage collection; the GC will free it
You never call "delete" — you simply stop referencing an object, and the GC takes care of the rest. This is a huge reason Java is so productive and safe to write.
OutOfMemoryError. That's usually a sign of a "memory leak" — objects you're accidentally keeping alive. Rare for beginners, but good to recognise.
I'll be honest: for a long time I wrote Java without thinking about the JVM at all — and that's fine, you can be productive without it. But when I finally understood the stack/heap split and how garbage collection works, a lot of things clicked at once: why == behaves as it does, why immutable objects are safe to share, why the occasional performance question even matters. You don't need to be a JVM expert, but this mental model quietly makes you better at everything else.
Key takeaways
- The JVM runs platform-independent bytecode, enabling "write once, run anywhere."
- Memory splits into the stack (method calls, locals, references) and the heap (objects created with
new). - The garbage collector automatically frees objects once nothing references them — no manual memory management.
- Holding references you don't need can cause a memory leak and eventually
OutOfMemoryError.
← Previous: Lesson 32 — Date & Time API
Next up: Data Structures & Algorithms in Java →
↑ Back to the full Java course roadmap