Java may be known for its “Write Once, Run Anywhere” mantra, but what makes it possible is the mighty Java Virtual Machine (JVM). Let’s explore its architecture, components, and the runtime journey of a Java application.
The Lifecycle of a Java Program
- When a Java application starts, the JVM boots up and creates a single thread — the main thread.
- This thread invokes the
main(String[] args)
method in the launcher class. - The
main()
method continues to run until the program exits normally or is explicitly terminated.
Event Loop in Action
- An infinite event loop runs inside
main()
— constantly polling the event queue. - If a task (i.e., a
Runnable
object) is present in the queue, it gets executed. - If the queue is empty, the loop continues to check until the program ends.
🛑 JVM can be explicitly shut down using
System.exit()
orRuntime.exit()
.
One JVM = One Application
- A single JVM instance serves one Java application — you cannot run multiple applications within the same JVM instance.
- Reference: Why One JVM Per App? – StackOverflow
Key JVM Classes and Interfaces
System.class
- Manages standard I/O streams:
System.in
: Standard Input (e.g., Keyboard)System.out
: Standard Output (e.g., Console)System.err
: Standard Error- Provides
loadLibrary()
method to load native libraries (e.g., written in C/C++).
Runtime.class
- Acts as the interface between the Java app and the underlying OS environment.
- Provides hooks to interact with system resources, memory, and process control.
Threads and Runnables
- Java’s
Thread
class implements theRunnable
interface. - A
Thread
object can be initialized with aRunnable
instance:
“`java
Runnable task = new MyTask();
Thread thread = new Thread(task);
JVM and Native Code
- JVM itself is a native application, typically written in C/C++.
- Java applications are compiled into bytecode, a platform-independent intermediate code.
JRE vs JDK vs JVM
Component | Description |
---|---|
JVM | Executes Java bytecode |
JRE (Java Runtime Environment) | JVM + Java Class Libraries + Native Libraries |
JDK (Java Development Kit) | JRE + Development Tools (javac, jar, etc.) |
Compilers: JIT vs AOT
Just-In-Time (JIT) Compiler
- Converts bytecode to native code at runtime.
- Native code is then executed by the CPU for improved performance.
Ahead-Of-Time (AOT) Compiler
- Compiles Java code directly into native binaries before runtime.
- Modern Java apps often use AOT to improve performance and reduce JVM dependency.
AOT enables Java apps to run like native apps without needing a JVM on the target machine.
Summary
The JVM is more than a runtime — it’s the brain behind Java’s portability. From bytecode interpretation to native execution, understanding how it works can help developers write more optimized, efficient, and scalable applications.