Skip to content

Guide

What is a stack frame in the JVM?

What the JVM creates for every method call: the local variable array, the operand stack and frame data, and how bytecode uses them.

Stack frame

JVM specification

Storage for one method invocation: local variables, operand stack and a link to the class's constant pool.

Simply put

A frame is the workspace of one method call. It holds the method's local variables and a small scratch stack for calculations, and it remembers how to get back to the caller.

What a developer sees

A frame lives exactly as long as one method call. Its local variables are the method’s parameters and locals; javac works out how many slots and how deep an operand stack each method needs (locals= and stack= in javap -v).

That is why local variables vanish when a method returns, and why a lambda can only use local variables that never change after they are set (effectively final): it gets a copy of the value, not the frame’s slot.

Picture it

A workspace set up for one task: a notepad for the task’s values and a small scratch pile for working things out, cleared away when the task is done.

The notepad

The local variable array

The scratch pile

The operand stack

Clearing away

The frame is removed when the method returns

Where the picture stops working

A real frame also holds what the JVM needs to return to the caller and to handle exceptions. Its slots hold primitive values and references only, never whole objects. And it is not a literal desk or box: the JIT compiler may keep a frame’s values in processor registers.

Deep dive: the specification and HotSpot in detail

JVMS §2.6: a frame is created each time a method is invoked and destroyed when the invocation completes, normally or abruptly. It contains a , an and a reference to the run-time constant pool of the current method's class (). Their sizes are fixed at compile time (max_locals, max_stack in the Code attribute: 3 and 3 for our main). Only one frame per thread is active: the current frame.

HotSpot's interpreter frame on x86-64 additionally stores the sender's stack pointer, the Method*, the class mirror, the profiling pointer (mdp), the constant pool cache, the locals pointer, the bcp and a monitor block. Compiled frames look different again: values live in registers and one physical frame can represent several inlined methods.

The specification requires

Locals, operand stack, and a reference to the run-time constant pool, with sizes fixed per method.

HotSpot (JDK 25) does

HotSpot: interpreter frames with extra slots (Method*, mdp, cpCache, bcp, monitors); compiled frames with register-allocated values and inlined callees.

Frame sizes are computed by javacOutput
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=3, args_size=1

Verified with OpenJDK 25.0.4 · Linux x64

Common misconceptions

  • Frames grow when a method needs more space.

    A frame's maximum size is fixed at compile time and checked by the verifier.

Sources

Local variable array

JVM specification

Indexed slots for a method's parameters and local variables; slot 0 is `this` in instance methods.

Simply put

Numbered boxes where a method keeps its parameters and local variables. In main, box 0 holds args, box 1 holds p1 and box 2 holds p2. A box can hold a number or a reference to an object, never the object itself.

Deep dive: the specification and HotSpot in detail

JVMS §2.6.1: an array of variables indexed from 0, sized by max_locals. Each slot holds a boolean, byte, char, short, int, float, reference or returnAddress; long and double occupy two consecutive slots. For instance methods slot 0 holds this; parameters follow in order. Instructions such as aload_1 and astore_2 move values between locals and the operand stack. Local names exist only in the optional LocalVariableTable (javac -g).

Slots of main() (javac -g, javap -c -l)Output
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      27     0  args   [Ljava/lang/String;
           10      17     1    p1   LPerson;
           12      15     2    p2   LPerson;

Verified with OpenJDK 25.0.4 · Linux x64

Common misconceptions

  • `p2 = p1` copies the Person object.

    It copies the reference value from slot 1 to slot 2 (aload_1, astore_2). Both slots now refer to the same heap object.

Sources

Operand stack

JVM specification

A per-frame LIFO scratch stack: instructions pop their inputs from it and push their results.

Simply put

The JVM is a stack machine. To compute something, it pushes values onto a small stack, and each instruction takes its inputs from the top and puts its result back on top.

Deep dive: the specification and HotSpot in detail

JVMS §2.6.2: each frame has an operand stack whose maximum depth (max_stack) is fixed at compile time. It starts empty. Load and constant instructions push; arithmetic, field and invoke instructions pop operands and push results; invocations pop the arguments and the callee's return value is pushed onto the caller's stack. The verifier proves the stack's depth and types at every instruction.

The operand stack is a model: the template interpreter caches the top value in a register, and compiled code maps stack slots to registers, so no physical operand stack exists in JIT-compiled methods.

new Person("Alex") on the operand stackOutput
0: new #7            // [ Person(uninitialized) ]
3: dup               // [ Person, Person ]
4: ldc #9            // [ Person, Person, "Alex" ]      ← depth 3 = max_stack
6: invokespecial #11 // [ Person ]  (<init> consumed two values)
9: astore_1          // [ ]         (reference stored in local 1)

Verified with OpenJDK 25.0.4 · Linux x64 (instructions from javap; stack states follow JVMS §6.5)

Common misconceptions

  • The operand stack is the same as the thread's stack.

    Each frame has its own small operand stack inside it. The thread's JVM stack holds the frames.

Sources

JVM Atlas

Explore the machine behind Java programs. A free, open-source atlas of the Java Virtual Machine. Specification baseline: Java SE 25. Implementation details: OpenJDK HotSpot, JDK 25.

MIT licensed · no accounts, no tracking, no backend · your progress stays in your browser.

JVM Atlas is an independent educational project and is not affiliated with or endorsed by Oracle. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.