Java Fundamentals: Inside the main() Method
The lifecycle of a Class Execution in Java
What Happens When We run a Java class with a main
the JVM performs several critical steps, from class loading to execution.
Let’s break it down in deep technical detail:
Compilation (if not already done)
Java source code (.java
) is compiled once to bytecode (.class
) using the javac
compiler:
This produces a MyApp.class
file containing platform-independent bytecode.
Class Loading
When you run:
Copyjava MyApp
The JVM kicks in and follows these steps:
a. Bootstrap ClassLoader
- Loads core Java classes (like
java.lang.Object
) fromrt.jar
or modular JDK classes.
b. Extension ClassLoader
- Loads classes from
JAVA_HOME/lib/ext
.
c. Application ClassLoader
- Loads your class (
MyApp
) from the classpath (e.g., current directory or.jar
file). - This follows the parent delegation model (child asks parent first).
Bytecode Verification
Before running, the JVM verifies the bytecode for security and correctness:
- No stack overflows
- Valid jumps (no jumping to invalid instructions)
- Type safety
- Ensures no tampered
.class
files
Class Initialization
Once verified:
- Static blocks (
static {}
) are run. - Static fields are initialized.
- Class metadata is loaded into method area.
- Other classes used inside
main
(like other utilities) will also be loaded lazily when needed.
Interpretation Begins
- The
main(String[] args)
method is invoked. - JVM uses its interpreter to start executing bytecode instruction by instruction.
JIT Compilation (Just-In-Time)
The HotSpot JVM monitors the code execution:
When a method is called repeatedly (hot method):
- It’s compiled from bytecode to native machine code by the JIT compiler.
- Native code is stored in memory, so future calls are super fast.
JIT has 3 levels:
- C1 (Client Compiler) — quick, less optimized.
- C2 (Server Compiler) — slower to compile, highly optimized.
- Graal (new JIT) — used in newer JVMs.
JIT optimizations include:
- Inlining methods
- Loop unrolling
- Escape analysis
- Dead code elimination
Execution Continues
- Now a mix of interpreted and compiled native code is being executed.
- JVM handles memory management (GC), threads, etc.
Garbage Collection (GC)
- JVM allocates objects on the heap.
- Unused objects are detected and cleaned by the GC (Garbage Collector).
- G1 GC, ZGC, Shenandoah, etc., depending on configuration.
Program Ends
- Once
main()
finishes: - JVM performs cleanup.
- All non-daemon threads are stopped.
- Classes may be unloaded.
- Exit code is returned to OS.