Handbooks / Java / Chapter 4

JVM and Memory

7 pages · ~5 min✓ Reviewed

Builds on Exceptions. Next up: Concurrency.

JavaPage 1

JDK, JRE and JVM Mental Model

1. Three layers

ContainsUse
JVMloads, runs bytecodeexecute
JREJVM + java.lang, java.utilrun, no compiler
JDKJRE + javac, jar, javadoc, jdb, jlink, jcmddevelop
  • Bytecode is platform-independent
  • The JVM is platform-specific: write once, run anywhere

2. Containment

  • JDK ⊃ JRE ⊃ JVM
  • Since Java 11 Oracle ships no separate JRE
  • Some vendors (Eclipse Temurin) still do
  • Use a JDK or a jlink-built runtime

3. Source to execution

  1. Hello.java
  2. javac
  3. Hello.classbytecode
  4. java launcherstarts JVM
  5. Class loader
  6. Execution engine
bash
javac Hello.java
java Hello

compile with the JDK, run on the JVM

No compiler?

javac: command not found means you have only a JRE. Install a JDK.

JavaPage 2

Bytecode, JIT and Class Loading

1. Bytecode and the JIT

  • Bytecode = stack-based, platform-neutral instructions in .class files
  • Engine interprets first, then JIT-compiles hot methods to native code
  • C1 = quick compile, C2 = optimizing; tiered uses both
bash
javac Hello.java
javap -c Hello

javap -c disassembles to bytecode

  • JIT tricks: inlining, escape analysis, dead-code elimination
  • Warm-up cost makes short benchmarks lie: use JMH

2. Class Loading

  1. Bootstrapcore JDK classes
  2. Platformformerly Extension
  3. Applicationclasspath
  • Each loader asks its parent first: user code cannot replace java.lang.String
  • Loading is lazy: on first use
  • Steps: load → link (verify, prepare, resolve) → initialize (static blocks run)

3. Missing Class Errors

ClassNotFoundExceptionNoClassDefFoundError
Kindchecked exceptionError
Whendynamic load fails, e.g. Class.forNamepresent at compile time, missing at runtime
Remember

Delegation goes up to Bootstrap first; a JIT benchmark needs warm-up before timing.

JavaPage 3

Stack vs Heap Memory

1. Stack and Heap

StackHeap
Scopeone per threadshared by all threads
Holdsframesobjects and arrays
Speedfast, LIFOslower
Freedauto on returnonly by GC
  • Frame = locals + operand stack + return address
  • Method call pushes a frame; return pops it

2. What Lives Where

  • Primitive local: the value sits in the stack frame
  • Object local: reference on the stack, object on the heap
  • Java is always pass-by-value: the reference is copied
java
int n = 5;  // value on stack
Point p = new Point();  // p on stack, object on heap
void move(Point q) { q.x = 9; q = null; }

caller's p still points to the object, with x changed

3. Errors and Tuning

ErrorCauseTune
StackOverflowErrortoo-deep or infinite recursion-Xss
OutOfMemoryError: Java heap spaceheap exhausted-Xms / -Xmx
Not on the stack, not all in the heap

Class metadata lives in Metaspace (native memory, Java 8+). Static fields live on the heap, held by the Class object.

JavaPage 4

Garbage Collection Basics

1. What Is Garbage

  • Eligible when no live GC root can reach it
  • Roots: thread stacks, static fields, JNI refs
  • No reference counting, so cycles are collected

2. Generations and Collectors

  1. Edennew objects
  2. S0 / S1survivors age
  3. Oldpromoted at threshold
  • Most objects die young
  • Minor GC: cleans Young, frequent, fast
  • Major/Full GC: Old and more, slow, long stop-the-world pauses
CollectorPick it for
Serialsmall apps
Parallelthroughput
G1default since Java 9, balanced low pause
ZGC / Shenandoahvery low pause, large heaps

3. Avoid and Tune

  • System.gc() is only a hint, no guarantee
  • finalize() is deprecated: use try-with-resources or Cleaner
bash
java -Xms512m -Xmx2g \
     -XX:+UseG1GC -Xlog:gc App

heap size, collector, GC log

Remember

GC frees only unreachable objects. Reachable but unused objects are a leak.

JavaPage 5

String Pool and Immutability

1. Immutable and Pooled

  • Immutable: value fixed after creation
  • concat, replace, toUpperCase return a new String
  • String pool: unique literals cached in the heap (Java 7+)
  • Same literal text shares one object
CodeResult
"hi"reuses or creates the pooled one
new String("hi")always a new heap object
s.intern()returns the pooled instance
  • == compares references; equals() compares content
java
String b = new String("a");
System.out.println("a" == "a");
System.out.println(b == "a");
System.out.println(b.equals("a"));
output
true
false
true

2. Why Immutable, and Loops

  • Safe pool sharing
  • Thread safety
  • Cached hashCode: safe HashMap keys
  • Security: class names, paths, credentials
Concat in loopThread-safeSpeed
s +=n/amany garbage objects
StringBuildernofast
StringBuffersynchronizedslower
Mistake

Compare content with equals(), never ==.

JavaPage 6

Memory Leaks and Cheat Sheet

1. What a Leak Is

  • Leak = objects still reachable but never used again
  • GC cannot free them, so it ends in OutOfMemoryError
CauseFix
Static collection only growsBounded cache or WeakHashMap
Unclosed stream, connectiontry-with-resources
Listener never deregisteredRemove listener on close
ThreadLocal in thread poolremove() in finally
Bad equals/hashCode keyOverride both consistently

2. Diagnose

  • Find the pid, check the heap, dump live objects
  • Open heap.hprof in Eclipse MAT or VisualVM
  • Add -XX:+HeapDumpOnOutOfMemoryError to the JVM flags
bash
jps
jcmd <pid> GC.heap_info
jmap -dump:live,format=b,file=heap.hprof <pid>

3. Cheat Sheet

  • JDK ⊃ JRE ⊃ JVM
  • javac then java; javap -c shows bytecode
  • Class loaders delegate to the parent first
  • Stack per thread, heap shared
  • Young → Old generations, G1 default
  • equals() for content, never ==
  • StringBuilder in loops
  • Heap dump on OOM
Pooled threads live on

A pooled thread never dies, so its ThreadLocal values stay. Always remove() in finally.

JavaPage 7

Check yourself

What do "hi" == new String("hi") and "hi".equals(new String("hi")) print?
  • false, then true
  • new String always makes a fresh heap object; the literal is the pooled one
  • == compares references, equals() compares content
A service adds every request to a static List and never removes anything. It ends in OutOfMemoryError. Will a bigger -Xmx fix it?
  • No, it only delays the crash
  • The static field is a GC root, so the objects stay reachable and GC cannot free them
  • Fix: bound the cache or remove entries
Class.forName("Missing") fails at runtime. Which is thrown, and is it checked?
  • ClassNotFoundException, which is checked
  • NoClassDefFoundError is the unchecked Error: the class was there at compile time but is missing at runtime