← Back to Home

How Java Works (Compilation & Execution Flow)

Understanding how Java works internally explains platform independence, performance, and many runtime errors seen in real projects. Java follows a two-step process: compilation and execution.

High-Level Flow

  1. Write Java source code (.java)
  2. Compile source code into bytecode (.class)
  3. Load bytecode into JVM
  4. Verify bytecode
  5. Execute bytecode using interpreter and JIT compiler
  6. JVM interacts with OS and hardware

Step 1: Writing Java Source Code

  • Developer writes code in a text file with .java extension
  • Code follows Java syntax rules
  • Code is platform dependent at this stage

Example:

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello Java");
    }
}
          

Step 2: Compilation (javac)

  • Java compiler (javac) compiles .java file
  • Checks:
  • Syntax errors
  • Type errors
  • Missing semicolons, brackets, etc.

Output:

  • .class file (bytecode)

Key Point:

Bytecode is platform independent.

Step 3: Class Loading (Class Loader)

Once execution starts using:

java Hello

The Class Loader Subsystem loads required classes into memory.

Types of Class Loaders

  • Bootstrap Class Loader – Loads core Java classes
  • Extension Class Loader – Loads extension classes
  • Application Class Loader – Loads user-defined classes

Why it matters:

Ensures correct and secure class loading.

Step 4: Bytecode Verification

  • JVM verifies bytecode before execution
  • Checks:
  • No illegal memory access
  • Stack integrity
  • Valid instructions

Why it matters:

Prevents malicious or corrupted code from running.

Step 5: Execution by JVM

Execution is handled by the Execution Engine, which has two parts:

a) Interpreter

  • Reads bytecode line by line
  • Converts it into machine instructions
  • Slower for repeated execution

b) JIT (Just-In-Time) Compiler

  • Identifies frequently executed code (hot spots)
  • Converts bytecode into native machine code
  • Caches compiled code for reuse

Why it matters:

Improves performance significantly.

Step 6: Runtime Memory Management

During execution, JVM manages memory using runtime areas:

  • Heap – Objects
  • Stack – Method calls, local variables
  • Method Area – Class metadata
  • PC Register – Current instruction
  • Native Method Stack – Native code

Garbage Collector (GC):

  • Automatically removes unused objects from heap

Step 7: Interaction with OS & Hardware

  • JVM communicates with OS
  • OS communicates with hardware
  • Same bytecode behaves consistently across platforms

This is how Java achieves:

Write Once, Run Anywhere

Visual Flow (Conceptual)

Hello.java
   ↓ (javac)
Hello.class (Bytecode)
   ↓
Class Loader
   ↓
Bytecode Verifier
   ↓
Execution Engine
   ├─ Interpreter
   └─ JIT Compiler
   ↓
Operating System
   ↓
Hardware
          

Summary Table

Stage Responsibility Output
Source Code Developer writes code .java
Compilation Syntax & type check .class
Class Loading Loads classes Memory
Verification Security check Verified bytecode
Execution Interpreter + JIT Machine code
Memory Mgmt GC & runtime areas Optimized execution

Common Mistakes by Beginners

  • Thinking Java is fully interpreted
  • Believing bytecode runs directly on OS
  • Ignoring JIT compiler role
  • Confusing compilation errors with runtime errors
  • Not understanding GC behavior

Interview-Ready Answers

Short answer:

Java works by compiling source code into bytecode, which is executed by the JVM using an interpreter and JIT compiler.

Detailed answer:

Java source code is compiled by javac into platform-independent bytecode. The JVM loads, verifies, and executes this bytecode using an interpreter and JIT compiler, while managing memory and interacting with the operating system.

Key Takeaway

Java separates compilation and execution, allowing bytecode to run on any system with a JVM, delivering portability, security, and performance.