Java follows the principle of “Write Once, Run Anywhere” (WORA). This is made possible through the Java Virtual Machine (JVM) which allows Java programs to run on any platform.
When you write and run a Java program, it goes through multiple steps:
-
Writing the code (
.javafile) -
Compilation (
.classfile → bytecode) -
Execution (JVM interprets bytecode)
The complete flow from source code to execution is as follows:
.java → javac compiler → .class (bytecode) → JVM → Machine Code
Each step has a specific role, explained below.
You first write Java code in a .java file using a text editor or IDE.
Example:
class Hello {
public static void main(String[] args) {
System.out.println("Hello Java");
}
}File saved as:
Hello.java
The Java Compiler (javac) converts the source code (.java) into bytecode (.class).
Command:
javac Hello.java
This generates:
Hello.class
-
Checks syntax and semantics.
-
Verifies class names and package structure.
-
Does not convert to native machine code.
-
Produces platform-independent bytecode.
The output of the compilation process is a .class file.
This file contains Java bytecode — instructions understandable by the JVM.
Bytecode is not machine-dependent, making Java platform-independent.
Example (bytecode view using javap -c Hello):
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String Hello Java
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
When you run the program:
java Hello
The Java Virtual Machine (JVM) loads the .class file, verifies bytecode, and executes it.
-
Class Loader: Loads
.classfiles into memory. -
Bytecode Verifier: Checks code for security and correctness.
-
Interpreter / JIT Compiler: Converts bytecode into machine code for execution.
-
Runtime Execution: Executes the native code on the host machine.
The Java Virtual Machine performs all runtime activities.
| Component | Description |
|---|---|
| Class Loader | Loads classes dynamically at runtime. |
| Bytecode Verifier | Ensures bytecode follows security and language rules. |
| Interpreter | Reads and executes bytecode line by line. |
| JIT Compiler | Compiles frequently used bytecode into native machine code for faster execution. |
| Garbage Collector | Frees unused memory automatically. |
| Runtime Data Areas | Memory regions where data is stored during execution. |
| Memory Area | Description |
|---|---|
| Method Area | Stores class-level data (static variables, constants, method code). |
| Heap | Stores objects and instance variables. |
| Stack | Stores method frames, local variables, and references. |
| PC Register | Holds address of current executing instruction. |
| Native Method Stack | Stores native (non-Java) method calls. |
The JIT Compiler improves performance by compiling bytecode to native machine code during execution.
- Initially, JVM interprets bytecode.
- Frequently executed sections (hot code) are compiled by JIT into native code.
- Native code runs directly on CPU → improves speed.
+-------------------+
| .java Source File |
+---------+---------+
|
v
+-------------------+
| javac Compiler |
+---------+---------+
|
v
+-------------------+
| .class Bytecode |
+---------+---------+
|
v
+---------------------------+
| Java Virtual Machine |
| - Class Loader |
| - Bytecode Verifier |
| - Interpreter / JIT |
| - Garbage Collector |
+---------------------------+
|
v
+-------------------+
| Machine Execution |
+-------------------+
Consider:
class Example {
public static void main(String[] args) {
int x = 5;
int y = 10;
System.out.println(x + y);
}
}Execution Process:
-
Save as
Example.java. -
Compile →
javac Example.java→ producesExample.class. -
Run →
java Example. -
JVM loads class, verifies, executes
main(). -
Output:
15
Java is platform-independent at bytecode level because the .class file runs on any machine with a JVM.
| Stage | Platform Dependence |
|---|---|
| Source Code (.java) | Platform-independent |
| Bytecode (.class) | Platform-independent |
| Machine Code | Platform-dependent |
Different OS have different JVMs (Windows JVM, Linux JVM, Mac JVM), but all understand the same bytecode.
| Component | Responsibility |
|---|---|
| JDK | Development tools (javac, jar, debugger, etc.) |
| JRE | Runtime environment (JVM + libraries) |
| JVM | Executes bytecode on the machine |
Because Java compiles source code into bytecode, which can run on any system with a JVM.
It converts bytecode into machine-specific code and executes it.
- JDK: Development + Runtime tools
- JRE: Runtime environment
- JVM: Execution engine
A platform-independent intermediate representation of compiled Java code executed by JVM.
It loads .class files dynamically into memory when required during execution.
-
Java programs go through Compilation → Bytecode → Execution stages.
-
javac converts
.javainto.class. -
JVM executes bytecode and provides platform independence.
-
JIT Compiler boosts runtime performance.
-
Garbage Collector manages memory automatically.