The JVM begins executing a program's bytecode via interpretation, which starts up quickly but runs slower than native code. Its Just-In-Time (JIT) compiler continuously profiles the running program, identifying “hot” methods and loops executed frequently enough to be worth the cost of compiling, then compiles specifically those paths to real native machine code, replacing the interpreted version while the program keeps running. Memory is organized into the heap (object storage, managed by the garbage collector) and the stack (one per thread, holding local variables and method call frames).
Interpretation, then JIT compilation
A long-running loop like this one is exactly the kind of code the JIT compiler targets — the first several thousand iterations run interpreted, and once the JVM's profiler determines this loop is genuinely "hot," it compiles it to native machine code on the fly, often making the same code noticeably faster later in the same run than it was at the start.
long sum = 0;
for (long i = 0; i < 100_000_000; i++) {
sum += i; // runs interpreted at first; JIT-compiled to native code once "hot"
}Heap and stack: where memory actually lives
Every thread gets its own stack; every object, regardless of which thread created it, lives on the single shared heap — which is exactly why objects need a garbage collector coordinating across threads, while stack memory is automatically reclaimed the instant a method returns.
void process() {
int localCount = 0; // lives on THIS thread's stack
User user = new User("Alice"); // the User OBJECT lives on the shared heap;
// only the reference "user" lives on the stack
} // localCount and the reference are gone the instant process() returns;
// the User object survives until the garbage collector determines nothing references itBytecode verification: a real security layer
Before executing any loaded class, the JVM's bytecode verifier checks that the bytecode is structurally valid and doesn't violate the type system or access rules — this matters because bytecode can come from an untrusted source (historically, applets downloaded over a network), and the verifier catches maliciously or accidentally corrupted bytecode before it ever runs.