Careeroza
Memory Areas
JVM Runtime Data Areas
┌──────────────────────── shared by all threads ─────────────────────────┐ │ HEAP: all objects and arrays METASPACE (native) │ │ ┌───────────────── Young ───────────────┐ ┌──────┐ class metadata, │ │ │ Eden │ Survivor S0 │ Survivor S1 │ │ Old │ method bytecode, │ │ └───────────────────────────────────────┘ └──────┘ static fields* │ └────────────────────────────────────────────────────────────────────────┘ ┌──────── per thread ────────┐ ┌──────── per thread ────────┐ │ JVM STACK: one frame per │ │ PC register, native stack │ │ method call (locals, args, │ └────────────────────────────┘ │ operand stack) │ └────────────────────────────┘ * static field values live with the Class object on the heap
| Area | Holds | Error when full | Size flag |
|---|---|---|---|
| Heap | objects, arrays, String pool | OutOfMemoryError: Java heap space | -Xms, -Xmx |
| Stack | frames: local variables, references, return address | StackOverflowError | -Xss |
| Metaspace | class metadata (replaced PermGen in Java 8) | OutOfMemoryError: Metaspace | -XX:MaxMetaspaceSize |
| Code cache | JIT-compiled native code | JIT stops compiling | -XX:ReservedCodeCacheSize |
Stack vs Heap in Code
Example
Local variables and references live on the stack; the objects they point to live on the heap. Java passes the reference by value: a method can change the object but not the caller's variable.
public class Main {
public static void main(String[] args) {
int qty = 1; // primitive value on main's stack frame
Cart cart = new Cart(); // reference on the stack, Cart object on the heap
update(qty, cart);
System.out.println("qty after call: " + qty);
System.out.println("items after call: " + cart.items);
reassign(cart);
System.out.println("items after reassign: " + cart.items);
}
static void update(int q, Cart c) { // new frame: copies of qty and of the reference
q = 99; // changes only the copy
c.items++; // changes the shared heap object
}
static void reassign(Cart c) {
c = new Cart(); // the caller's reference is untouched
c.items = 500;
}
}
class Cart { int items = 0; }Output
qty after call: 1 items after call: 1 items after reassign: 1
StackOverflowError
Example
Every call adds a frame. Infinite recursion fills the thread stack.
public class Main {
static int depth = 0;
static void recurse() { depth++; recurse(); }
public static void main(String[] args) {
try {
recurse();
} catch (StackOverflowError e) {
System.out.println("Caught StackOverflowError after more than 1000 frames: " + (depth > 1000));
}
}
}Output
Caught StackOverflowError after more than 1000 frames: true