How a Java Program Runs
From Source to Execution
Many languages compile directly to machine code. Java adds a middle step, which is what gives it portability.
Step 1: Compilation
The compiler (javac) reads your .java source file and converts it into platform-neutral instructions called bytecode, saved in a .class file. Bytecode is not machine code; it is a compact instruction set understood by the JVM.
Step 2: Loading and Verification
When you run java MyProgram, the JVM has three jobs before doing any real work. The class loader finds and loads the class. The bytecode verifier inspects the bytecode and rejects unsafe constructs, such as code that tries to cast objects illegally or break out of array bounds. This verification is a major part of Java's security model.
Step 3: Execution
The execution engine then runs the bytecode. Early JVMs were pure interpreters, which were slow. Modern JVMs use a Just-In-Time (JIT) compiler that watches which parts of the bytecode run frequently and translates those hot paths into native machine code, making Java almost as fast as compiled languages for typical workloads.
Step 4: Memory Management
As objects are created, they live on the heap. You never free them yourself; the garbage collector finds objects the program can no longer reach and reclaims their memory, preventing memory leaks.
Write Once, Run Anywhere
Because the .class file is the same on every platform, you can compile on Windows and run the bytecode on Linux or macOS, as long as a JVM for that platform is installed.



.javasource becomes.classbytecode viajavac.- The JVM loads, verifies, JIT-compiles and runs the bytecode.
- Garbage collection frees you from manual memory management.