JDK vs JRE vs JVM — what's the difference?
EasyThe JVM runs bytecode: it loads classes, verifies them, interprets or JIT-compiles them, and collects garbage. The JRE is a JVM plus the standard libraries, enough to run apps. The JDK adds tools to build them: javac, jar, jshell, jlink and more.
How it works
- JVM (Java Virtual Machine). An abstract machine defined by a spec, with many implementations (HotSpot in OpenJDK, Eclipse OpenJ9, GraalVM).
- Loads
.classfiles and verifies the bytecode is safe. - Runs it with an interpreter at first, then JIT-compiles hot methods to native code.
- Manages memory and garbage collection, threads, and the link to the OS.
- The JVM itself is platform-specific; the bytecode it runs is not. That's "write once, run anywhere".
- Loads
- JRE (Java Runtime Environment). A JVM plus the Java class libraries (
java.base,java.sql,java.net.http...). It's what a machine needs to run Java. - JDK (Java Development Kit). A full runtime plus developer tools:
javac(compiler),jar,javadoc,jshell(REPL)jdb,jcmd,jstack,jfrfor debugging and profilingjlinkandjpackagefor building custom runtimes and installers
- Modern packaging. Since Java 11, Oracle no longer ships a separate JRE. Some distributions (Eclipse Temurin, for one) still publish JRE builds, but the recommended path is a JDK for development and, for production, a trimmed runtime built with
jlinkthat holds only the modules your app needs.
Example
// Greeter.java
public class Greeter {
public static void main(String[] args) {
System.out.println("Running on " + System.getProperty("java.vm.name")
+ " " + Runtime.version());
}
}$ javac Greeter.java # JDK tool: produces Greeter.class
$ java Greeter # JVM runs the bytecode
$ java Greeter.java # Java 11+: compile in memory and run a single file
$ jlink --add-modules java.base --output myruntime # tiny custom runtimeEdge cases
java Greeter.java(JEP 330, Java 11) launches a single source file without a separatejavacstep. Java 22 extended this to programs spread over several source files.- The same
.classfile runs on any JVM of the same or newer version. Running it on an older JVM fails withUnsupportedClassVersionError. - The JIT means a Java program usually gets faster after warm-up, which matters for benchmarks and short-lived CLI tools.
Common mistakes
- Saying the JVM is platform-independent. The bytecode is; each OS and CPU needs its own JVM build.
- Thinking you need a JDK on production servers "because Java". You need a runtime; a
jlinkimage is smaller and has less attack surface. - Mixing up "Java version" for compile and run:
javac --release 17targets 17 even when built with a JDK 21.
Likely follow-up
"What happens between java Greeter and main running?" The JVM starts, the bootstrap and platform class loaders load core classes, the application class loader loads Greeter, the bytecode is verified, static initializers run, and then main is invoked on the main thread.
Get every deep dive in the app
Coming soon to the App StoreComing soon to Google Play