← Learn Runs in your browser

Step 1 Source becomes bytecode

You write .java files; the compiler javac turns them into .class files containing bytecode — a compact instruction set for an imaginary stack machine. Bytecode is not native CPU code; it is portable, which is the whole "write once, run anywhere" idea. The JVM is what reads it.

Pick a snippet to disassemble

Java source
Bytecode (as javap -c would show)

Each line is one operation on an operand stack: push values, do arithmetic, call methods, store results. The JVM executes these one by one.

Step 2 Class loading & the delegation chain

Classes are loaded lazily, the first time they are needed. The JVM uses a hierarchy of class loaders, and each one asks its parent first (the parent-delegation model) so core classes can never be spoofed by your code. Loading happens in three phases: load the bytes, link (verify + prepare + resolve), then initialize (run static initializers).

Request a class — watch delegation walk up, then load walk down

Click a class above. A loader delegates upward first; whichever loader owns that class loads it.

Step 3 Interpret first, then JIT-compile the hot paths

The JVM starts by interpreting bytecode — simple and instant to start, but slow. Meanwhile it counts how often each method runs. Once a method gets "hot" (crosses an invocation threshold), the Just-In-Time compiler (HotSpot's C1/C2) compiles it to optimized native machine code, so later calls run at full speed. This is why a JVM program speeds up after it "warms up".

Call a method repeatedly and watch it get compiled

Invocations: 0
warm-upInterpreted

Below the threshold the method is interpreted. After ~10,000 calls HotSpot compiles it; per-call cost drops sharply.

Step 4 The stack and the heap

Each thread has its own stack: a frame is pushed for every method call (holding its local variables and partial results) and popped when it returns. All objects live on the shared heap; variables on the stack just hold references (pointers) into it. The stack is tiny and fast; the heap is large and garbage-collected.

Call methods and allocate — see frames and objects

Thread stack (grows down)
Heap (shared)

Returning pops the top frame. Objects it created stay on the heap until nothing references them — that is the garbage collector's job.

Step 5 Garbage collection

You never free() in Java. The GC periodically finds objects that are no longer reachable from your live references and reclaims their memory. Most collectors are generational: new objects go in the young generation (collected often and cheaply, since most die young); survivors are promoted to the old generation (collected rarely).

Allocate, drop references, then collect

Young generation
Old generation (promoted survivors)
reachableunreachable (will be collected)

Allocate some objects, drop a few references, then run GC: unreachable objects vanish and survivors are promoted to the old generation.

Step 6 Glossary

TermIn one sentence
bytecodePortable instructions in a .class file that the JVM executes.
JIT (HotSpot)Compiles frequently-run bytecode to native code at runtime for speed.
class loaderFinds and loads classes on demand, delegating to its parent first.
heapShared memory where all objects live; managed by the GC.
stack framePer-call slice of a thread's stack holding locals and operands.
GCReclaims unreachable objects automatically; usually generational.
JDK / JREJDK = tools + compiler to build; JRE = just enough to run.

The full loop: javac → bytecode → load → verify → interpret → JIT-compile hot paths, with the heap and GC handling memory throughout. The same machine runs any language that emits JVM bytecode.

Send feedback

How this works

Stores only this report's id in your browser (localStorage) so a small note can pop up here once it ships. No account, nothing sent to us, no tracking. Clearing this site's data forgets it.

Changelog

What changed, and when. Newest first.

Loading…