Detailed explanation
The Java Virtual Machine (JVM) is an abstract computing machine that executes Java bytecode. It is defined by a specification, while implementations such as HotSpot provide the software that runs on an actual operating system and processor. The JVM sits between compiled Java code and the underlying platform, allowing developers to distribute bytecode rather than a separate native executable for every machine. It also supports other languages, such as Kotlin, when they compile to compatible JVM bytecode.
The execution flow starts with compilation: `javac Hello.java` produces `Hello.class`, which contains bytecode rather than processor-specific machine instructions. Running `java Hello` starts a JVM through the Java launcher and launches the class's entry point, typically `public static void main(String[] args)`. Class loaders locate and load the required classes. During linking, the JVM verifies bytecode for structural and type-safety rules, prepares static storage, and resolves symbolic references as needed. Class initialisation then executes static initialisers before the class is actively used.
In a typical HotSpot execution, the interpreter initially executes bytecode, while the runtime collects information about frequently executed code. The Just-In-Time (JIT) compiler can compile hot methods or loops into native machine code for faster execution. Not every method must be JIT-compiled, and these execution strategies are implementation details rather than requirements of the JVM specification. The JVM also manages runtime memory: objects generally occupy the heap, and each thread has a JVM stack containing method-call frames, local variables, and operand stacks. Garbage collection automatically reclaims heap memory occupied by objects that are no longer reachable.
The JVM enables 'Write Once, Run Anywhere' because the same compatible bytecode can run on different platforms with suitable JVM implementations. The JVM implementation itself is platform-specific, and portability still depends on factors such as supported class-file versions and native-library dependencies. In interviews, clearly distinguish the JVM from the JDK: the JVM executes bytecode, while the JDK supplies development tools such as `javac` along with the runtime components needed to run Java applications.
Key points to remember
- The JVM executes Java bytecode, not Java source code directly.
- Class loading, linking, and initialisation prepare classes for execution.
- Typical JVMs combine interpretation with JIT compilation of frequently executed code.
- The JVM manages runtime memory and provides automatic garbage collection.
- Compatible bytecode is portable; JVM implementations are platform-specific.
Common mistakes candidates make
- Confusing the JVM with `javac`: the compiler produces bytecode, while the JVM executes it.
- Saying the JVM itself is platform-independent instead of explaining that each platform needs a suitable implementation.
- Claiming every method is immediately JIT-compiled or that garbage collection prevents all memory leaks.
Likely follow-up questions
What is the difference between JVM, JRE, and JDK?
The JVM executes bytecode, while the JRE traditionally bundles a JVM and the libraries needed to run applications. The JDK includes development tools such as the compiler and debugger, plus runtime components; modern distributions do not always offer a separate JRE package.
How is the JIT compiler different from javac?
`javac` compiles Java source code into bytecode before execution. The JIT compiler works during execution, translating selected bytecode into native machine code using runtime profiling information.
Can the same .class file run on any JVM?
It can run on JVMs that support its class-file version and provide the required libraries and features. Native dependencies and platform-specific assumptions can still prevent an application from running unchanged.
Interview tip: Define the JVM, walk through `Hello.java → javac → Hello.class → JVM`, and finish with portability and memory management.
