How Java works

Pick a topic, write code and watch what happens inside, step by step.

Memory

Collections

Concurrency

Language and JVM

Topics

Bytecode

The JVM is a stack machine

javac turns Java into bytecode and javap -c shows it. Instead of CPU registers, the JVM uses a small operand stack in each frame.

Every instruction pushes a value or pops one. For a + b, two values are pushed, and iadd pops them and pushes the result.

Local variables have no names, only slot numbers: istore_0 writes to slot 0.

javac calculates ahead

The code says 1 + 2, but the bytecode has no addition: iconst_3. The compiler works out constant expressions itself.

The same goes for "a" + "b": the result is one literal. That is why "ab" == "a" + "b" is true.

The i = i++ trap

This code does not change i: the result is 5. Follow the steps: iload_0 pushes the old 5, iinc makes i 6, and istore_0 writes the old 5 back.

Switch to i = ++i with the button: the order changes, iinc first, then iload_0. The result is 6.

A loop: if and goto

Bytecode has no for, only conditional and unconditional jumps. if_icmpgt pops two values and compares them, and goto jumps back.

Note that the condition is inverted: i <= 3 is written as "leave if i > 3".

A method call: a new frame

The caller pushes the argument. invokestatic creates a new frame, and the value moves to its slot 0.

ireturn removes the frame and pushes the result onto the operand stack of the caller. A stack overflow is these frames filling up.

How does finally work?

This method returns 1, not 2. javac first stores the return value in a separate slot (saved), then runs the finally code, then returns saved.

finally is not a separate block in bytecode: its code is copied into every exit path. The exception path starts at line 8 and does not run here, as there is no exception.

Autoboxing becomes visible

The Java code has no Integer.valueOf, but the bytecode does. Integer b = 4 is really Integer.valueOf(4), and that is where the Integer cache works.

For b + 1, intValue() is called first. If b were null, the NullPointerException would come from here.

String concatenation is similar: a + "!" becomes makeConcatWithConstants through invokedynamic.