Java Notes
Deep explanation of JDK, JRE, and JVM — what each contains, how they relate, the JVM architecture with class loader, memory areas, execution engine, and practical differences for developers.
These three acronyms — JDK, JRE, and JVM — are the foundation of Java's platform. Understanding what each contains and how they relate is crucial for both development and interview success.
The Relationship: JDK ⊃ JRE ⊃ JVM
Think of it as concentric circles:
JVM (Java Virtual Machine)
The JVM is an abstract computing machine that provides the runtime environment for executing Java bytecode. It's "virtual" because it doesn't correspond to any physical hardware — it's a software specification.
What the JVM Does
Class loaded by: jdk.internal.loader.ClassLoaders$AppClassLoader@251a69d7 Current thread: main Max memory: 4096 MB Free memory: 252 MB Available processors: 8
JVM Architecture — Detailed Breakdown
1. Class Loader Subsystem
The Class Loader is responsible for loading .class files into memory:
String ClassLoader: null Platform ClassLoader: jdk.internal.loader.ClassLoaders$PlatformClassLoader@1d81eb93 App ClassLoader: jdk.internal.loader.ClassLoaders$AppClassLoader@251a69d7 Parent of App: jdk.internal.loader.ClassLoaders$PlatformClassLoader@1d81eb93 Parent of Platform: null
Class Loading Phases:
| Phase | What Happens |
|---|---|
| Loading | Reads .class file, creates Class object |
| Linking - Verification | Checks bytecode is valid and safe |
| Linking - Preparation | Allocates memory for static fields (default values) |
| Linking - Resolution | Resolves symbolic references to direct references |
| Initialization | Runs static initializers and assigns static field values |
2. JVM Memory Areas (Runtime Data Areas)
public class MemoryAreasDemo {
// Static field → Method Area (shared across threads)
private static String appName = "MemoryDemo";
// Instance field → stored in Heap (when object is created)
private int instanceVar = 42;
public static void main(String[] args) {
// 'args' → Stack (local variable)
// 'obj' reference → Stack, actual object → Heap
MemoryAreasDemo obj = new MemoryAreasDemo();
int localVar = 100; // → Stack
String str = "Hello"; // → String Pool (part of Heap)
obj.demonstrate(localVar);
}
public void demonstrate(int param) {
// 'param' → new Stack frame
// 'temp' → Stack frame
int temp = param + instanceVar;
System.out.println("Result: " + temp);
// When this method returns, its stack frame is destroyed
}
}Result: 142
JVM Memory Areas Explained:
| Area | Content | Shared? | Lifecycle |
|---|---|---|---|
| Method Area | Class metadata, static fields, constant pool, method bytecode | Yes (all threads) | Lives until class is unloaded |
| Heap | All objects and arrays | Yes (all threads) | Until garbage collected |
| Stack | Local variables, method parameters, return addresses | No (per thread) | Per method call (frame) |
| PC Register | Address of currently executing instruction | No (per thread) | Changes with each instruction |
| Native Method Stack | Data for native (C/C++) methods | No (per thread) | During native calls |
3. Execution Engine
The Execution Engine converts bytecode to native machine code:
Sum: 100000000000000 Time: 23 ms (JIT made this faster than pure interpretation)
JRE (Java Runtime Environment)
The JRE is everything needed to RUN Java programs (but not develop them):
What's Inside the JRE
JRE Components
| Component | Purpose |
|---|---|
| JVM | Executes bytecode |
| Core Libraries | java.lang, java.util, java.io, etc. |
| java launcher | The java command to run programs |
| Configuration | security, networking, logging settings |
| Native libraries | Platform-specific implementations |
// JRE provides all the standard libraries:
import java.util.*; // Collections, Date, etc.
import java.io.*; // File I/O
import java.net.*; // Networking
import java.math.*; // BigDecimal, BigInteger
import java.time.*; // Date/Time API
public class JRELibrariesDemo {
public static void main(String[] args) {
// All these work because JRE includes the standard library:
// Collections
List<String> list = new ArrayList<>(List.of("A", "B", "C"));
System.out.println("List: " + list);
// Date/Time
LocalDateTime now = LocalDateTime.now();
System.out.println("Now: " + now);
// Math
BigDecimal price = new BigDecimal("19.99");
BigDecimal tax = price.multiply(new BigDecimal("0.08"));
System.out.println("Tax: $" + tax);
// System info (from JRE)
System.out.println("Java Home: " + System.getProperty("java.home"));
}
}List: [A, B, C] Now: 2024-01-15T14:30:00.123456 Tax: $1.5992 Java Home: /usr/lib/jvm/java-21-openjdk/
Note: Since Java 9's module system, a standalone JRE is no longer distributed separately. The JDK contains everything, and you can create custom runtime images with jlink.
JDK (Java Development Kit)
The JDK is the complete development environment — it includes the JRE plus development tools.
What's Inside the JDK (that's NOT in JRE)
Using JDK Tools
// 1. javac — Compile source to bytecode
// $ javac HelloWorld.java
// → produces HelloWorld.class
// 2. java — Run the bytecode
// $ java HelloWorld
// → JVM executes the bytecode
// 3. javap — Disassemble class files (see bytecode!)
// $ javap -c HelloWorld.class
public class JDKToolsDemo {
public static void main(String[] args) {
System.out.println("Compile me with: javac JDKToolsDemo.java");
System.out.println("Run me with: java JDKToolsDemo");
System.out.println("Disassemble with: javap -c JDKToolsDemo.class");
System.out.println("Debug with: jdb JDKToolsDemo");
System.out.println("Monitor with: jconsole");
}
}Compile me with: javac JDKToolsDemo.java Run me with: java JDKToolsDemo Disassemble with: javap -c JDKToolsDemo.class Debug with: jdb JDKToolsDemo Monitor with: jconsole
Seeing Bytecode with javap
public class BytecodeDemo {
public static int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
int result = add(3, 4);
System.out.println(result);
}
}
// Compile: javac BytecodeDemo.java
// Disassemble: javap -c BytecodeDemo.class
// Output shows actual bytecode:// javap -c BytecodeDemo.class output:
public static int add(int, int);
Code:
0: iload_0 // push first argument onto stack
1: iload_1 // push second argument onto stack
2: iadd // pop both, add them, push result
3: ireturn // return the int on top of stack
public static void main(java.lang.String[]);
Code:
0: iconst_3 // push constant 3
1: iconst_4 // push constant 4
2: invokestatic #2 // call add(int, int)
5: istore_1 // store result in local variable 1
6: getstatic #3 // get System.out
9: iload_1 // load the result
10: invokevirtual #4 // call println(int)
13: returnComparison Table
| Feature | JVM | JRE | JDK |
|---|---|---|---|
| Executes bytecode | ✅ | ✅ | ✅ |
| Standard libraries | ❌ | ✅ | ✅ |
Java launcher (java) | ❌ | ✅ | ✅ |
Java compiler (javac) | ❌ | ❌ | ✅ |
Debugger (jdb) | ❌ | ❌ | ✅ |
| javadoc | ❌ | ❌ | ✅ |
| jshell (REPL) | ❌ | ❌ | ✅ |
| Monitoring tools | ❌ | ❌ | ✅ |
| Who needs it? | Part of JRE | End users | Developers |
| Purpose | Execute | Run programs | Develop + Run |
JDK Distributions
Multiple vendors provide JDK implementations:
| Distribution | Vendor | License | Best For |
|---|---|---|---|
| Oracle JDK | Oracle | Commercial (free for dev) | Enterprise with support |
| OpenJDK | Oracle/Community | Open source (GPL v2) | Reference implementation |
| Amazon Corretto | Amazon | Free, open source | AWS deployments |
| Eclipse Temurin | Adoptium | Free, open source | General purpose |
| Azul Zulu | Azul Systems | Free + paid support | Enterprise |
| GraalVM | Oracle | Dual license | Polyglot, native compilation |
| Microsoft Build | Microsoft | Free, open source | Azure deployments |
public class DistributionCheck {
public static void main(String[] args) {
// Check which distribution you're running:
System.out.println("Implementation: " +
System.getProperty("java.runtime.name"));
System.out.println("Version: " +
System.getProperty("java.runtime.version"));
System.out.println("Vendor: " +
System.getProperty("java.vendor"));
System.out.println("VM: " +
System.getProperty("java.vm.name"));
}
}Implementation: OpenJDK Runtime Environment Version: 21.0.1+12-29 Vendor: Eclipse Adoptium VM: OpenJDK 64-Bit Server VM
JVM Languages
The JVM doesn't only run Java — any language that compiles to bytecode can run on it:
| Language | Paradigm | Use Case |
|---|---|---|
| Java | OOP, Functional | Enterprise, Android |
| Kotlin | OOP, Functional | Android (preferred), Backend |
| Scala | OOP, Functional | Big Data (Spark), Backend |
| Groovy | OOP, Scripting | Gradle build scripts, testing |
| Clojure | Functional, Lisp | Data processing |
| JRuby | OOP, Scripting | Ruby on JVM |
| Jython | OOP, Scripting | Python on JVM |
Common Mistakes
- Thinking you need both JDK and JRE installed — JDK already includes the JRE. You only need the JDK for development.
- Confusing JVM specification with implementation — "JVM" is a specification (a document). HotSpot, GraalVM, OpenJ9 are implementations of that specification.
- Thinking all JVMs are the same — Different implementations (HotSpot vs GraalVM vs OpenJ9) have different performance characteristics and features.
- Not understanding JIT compilation — The JVM starts by interpreting bytecode (fast startup) and then JIT-compiles hot code to native code (fast execution). This means Java programs get faster over time.
- Assuming JRE still exists as separate download — Since Java 11, Oracle no longer ships a standalone JRE. You either use the full JDK or create a custom runtime with
jlink. - Mixing up ClassLoaders — Bootstrap loads java.lang.*, Platform loads extension libraries, Application loads your code. Understanding delegation prevents ClassNotFoundException.
Best Practices
- Always install the JDK (not just JRE) — even for testing, you'll want tools like
javapandjshell - Use a mainstream distribution — Eclipse Temurin (Adoptium) or Amazon Corretto for free, production-ready JDKs
- Match JDK versions across development and production environments
- Use
jlinkto create minimal custom runtimes for deployment (reduces image size) - Monitor JVM with
jconsoleorjvisualvmto understand memory and thread behavior
Interview Questions
Q1: What is the difference between JDK, JRE, and JVM?
Answer: JVM (Java Virtual Machine) is the abstract machine that executes bytecode — it handles class loading, memory management, and execution. JRE (Java Runtime Environment) includes the JVM plus the standard libraries needed to run Java programs. JDK (Java Development Kit) includes the JRE plus development tools (compiler javac, debugger jdb, documentation tool javadoc, etc.) needed to write and compile Java programs.
Q2: Can Java run without JVM?
Answer: Traditional Java requires a JVM. However, GraalVM Native Image can compile Java directly to native executables (ahead-of-time compilation), eliminating the JVM at runtime. Also, some embedded Java implementations use alternative execution models. But standard Java programs require a JVM.
Q3: What are the main components of JVM architecture?
Answer: The JVM has three main subsystems: (1) Class Loader — loads, verifies, and prepares classes; (2) Runtime Memory Areas — Method Area (class data), Heap (objects), Stack (local variables/method calls), PC Register, Native Method Stack; (3) Execution Engine — Interpreter (line-by-line), JIT Compiler (hot code to native), Garbage Collector (memory reclamation).
Q4: What is JIT compilation?
Answer: JIT (Just-In-Time) compilation is the process where the JVM identifies "hot" methods (frequently called) and compiles their bytecode into native machine code at runtime. This eliminates the overhead of interpretation for hot code paths, allowing Java to achieve performance comparable to natively compiled languages. The JIT compiler also performs optimizations like inlining, loop unrolling, and escape analysis.
Q5: Why are there different JDK distributions? Which should I use?
Answer: Different vendors provide JDK distributions with varying licensing, support, and optimizations. Oracle JDK has commercial licensing for production. Eclipse Temurin (Adoptium) is the community-recommended free distribution. Amazon Corretto is optimized for AWS. GraalVM adds polyglot support and native compilation. For most developers, Eclipse Temurin or Amazon Corretto is the best free choice.
Summary
The JDK is what you install as a developer — it contains everything (compiler, debugger, JRE, JVM). The JRE is what end users need to run Java programs (JVM + libraries). The JVM is the engine that executes bytecode through class loading, memory management, and the execution engine (interpreter + JIT). Understanding this hierarchy clarifies how Java achieves platform independence and helps you make informed decisions about JDK distributions and deployment strategies.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for JDK, JRE, and JVM.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Java Master Course topic.
Search Terms
java-master-course, java master course, java, master, course, fundamentals, introduction, jdk
Related Java Master Course Topics