Topic 0.2
What Java Is: JDK, JRE, JVM and Bytecode
In one line
Java is a programming language plus a platform to run it. The javac compiler turns your .java files into portable bytecode (.class files), and a Java Virtual Machine on each computer runs that same bytecode, which is why one compiled program works on Windows, macOS and Linux. The JDK is the toolbox for writing Java; the JVM is the engine that runs it.
Think of it like this
Sheet music. A composer writes a song once, as sheet music. A pianist in India, Brazil or Japan can play it, because every pianist knows how to read sheet music and turn it into sound on their own piano. In Java, your program is compiled once into bytecode (the sheet music), and every computer has a Java Virtual Machine (the pianist) that knows how to play bytecode on its own kind of chip.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Compiler
- A program that translates your whole source code into another form before it runs. Java's compiler is
javac. - Bytecode
- The instructions inside a
.classfile. They are written for the JVM, not for a real chip, so the same file runs on any computer with a JVM. - Class file
- The file
javacproduces from your source, such asMain.class. One is made for every class in your code. - JVM
- Java Virtual Machine: the program that loads and runs bytecode on a real computer. You start it with the
javacommand. - JDK
- Java Development Kit: everything you install to write and run Java, including
javac,java,jshelland the standard library. - JRE
- Java Runtime Environment: the JVM plus the standard library, without the developer tools. Older Java versions shipped it separately.
- Standard library
- Thousands of ready-made classes that come with Java, such as
String,MathandArrayList, so you don't write everything yourself. - Platform independent
- Works on any operating system and chip. Java bytecode is platform independent; each JVM is built for one platform.
- Garbage collector
- The part of the JVM that automatically frees memory used by objects your program no longer needs.
- Distribution
- A ready-to-install JDK built from OpenJDK by a vendor, such as Eclipse Temurin or Amazon Corretto.
Step by step
01Two jobs: translate, then run
Running Java is a two-step job, done by two different programs. First the compiler javac translates your source into bytecode and saves it as a .class file. Second, the JVM (started with java) runs that bytecode.
You can compile on a Windows laptop, copy Main.class to a Linux server and a Mac, and run it on all three without compiling again. Each machine needs its own JVM, but the class file is the same.
02What the compiler checks and produces
javac does more than translate. It reads the whole file and checks Java's rules: every statement is well formed, every name you use exists, and every value has the right type (you can't store text in a number box). If anything is wrong, it prints errors and produces no class file. That is why many Java mistakes are caught before the program ever runs.
If everything is fine, it writes one .class file per class. A source file with two classes produces two class files.
class Greeter {
String greet(String name) {
return "Hello, " + name + "!";
}
}
public class Main {
public static void main(String[] args) {
Greeter g = new Greeter();
System.out.println(g.greet("Asha"));
}
}03Peek inside a class file with javap
Bytecode is not secret. The JDK tool javap -c prints it in a readable form. Below is a small method add(int x, int y) { return x + y; } after compilation. The JVM is a stack machine: instructions push values onto a small work pile called the operand stack, and other instructions pop them off and work on them.
iload_0 pushes the first argument, iload_1 pushes the second, iadd pops both and pushes their sum, ireturn returns the top value. The i means "int". You will never write bytecode by hand, but knowing it exists explains how Java runs (Topic 0.8).
04The JVM: a pretend computer inside your real one
The word virtual means "not physical, made in software". The JVM is a program written mostly in C++ that behaves like a computer whose machine code is bytecode. When you type java Main, the operating system starts the JVM, and the JVM then loads Main.class and runs its main method.
Because every JVM obeys the same written rules (the Java Virtual Machine Specification), the same bytecode gives the same results everywhere. int is always 32 bits, 0.1 + 0.2 prints the same digits on every machine, and the order of evaluation is fixed. The first runnable example below shows numbers that are identical on any JVM.
05JDK, JRE, JVM: boxes inside boxes
Picture three nested boxes. The innermost is the JVM, the engine that runs bytecode. Around it is the JRE, which adds the standard library the engine needs (String, Math, collections, files). Around that is the JDK, which adds the developer tools (javac, jshell, javap, jar...).
To run Java programs you need at least a runtime. To write them you need the JDK. Today you install a JDK either way. For servers, teams often use jlink to build a slim runtime containing only the parts their app uses.
06One language, many distributions
Java is developed in the open as OpenJDK. Vendors build it, test it, and publish installers: Eclipse Temurin (from the Adoptium group), Oracle JDK, Amazon Corretto, Azul Zulu, Microsoft Build of OpenJDK, Red Hat build of OpenJDK and others. They differ in support offerings and licences, not in the language.
The engine inside nearly all of them is HotSpot, the JVM that started at Sun Microsystems. Other JVMs exist, such as Eclipse OpenJ9 and GraalVM, and all of them must pass the official compatibility tests to call themselves Java.
07Java is not JavaScript
Java (1995, Sun Microsystems) and JavaScript (1995, Netscape) share part of a name because of a marketing deal, and they both use curly braces. That is where the similarity ends. JavaScript usually runs inside web browsers and checks types while the program runs. Java runs on the JVM and checks types before the program runs.
If you search the web for help, include the word "Java" and not "JS", or you'll get answers for the wrong language.
Try it yourself
- 1
Find the class files
On your own machine (after Topic 0.4), save the first example as
Main.java, runjavac Main.java, and list the folder. You should seeMain.classandGreeter.class. DeleteGreeter.classand runjava Main: the JVM fails withNoClassDefFoundError: Greeter, because it loads classes from files when they are first needed.terminal$ javac Main.javajava Main── expected output ──Hello, Asha!Hello, Ben!This file compiled into Main.class and Greeter.class. - 2
Read your own bytecode
Run
javap -c Mainon the class you just compiled. Findinvokevirtuallines: each one is a method call. Findldclines: each loads a constant, such as your text"Hello, ". - 3
Predict the overflow
In the second example, change
Integer.MAX_VALUE + 1toInteger.MAX_VALUE + 2. Predict the output before you run it. (It is-2147483647: the value wraps around like a car's odometer. Topic 1.3 explains why.)
Code & diagrams
javac writes Greeter.class and Main.class. The JVM loads Greeter only when main first uses it.
Expected output
Hello, Asha!
Hello, Ben!
This file compiled into Main.class and Greeter.class.The Java specification fixes the size of int and the rules of arithmetic, so these lines print exactly the same on Windows, macOS, Linux and in the browser.
Expected output
Biggest int: 2147483647
Biggest int + 1: -2147483648
0.1 + 0.2 = 0.30000000000000004
7 / 2 = 3
An int uses 4 bytesMath, String and List come with every JDK. You didn't write them, and you don't install anything extra to use them.
Expected output
Square root of 81: 9.0
Bigger of 7 and 12: 12
Shout: JAVA
Fruits: [mango, apple]Real output of `javap -c Main` (JDK 21) for a program whose main adds two ints with add(a, b) and prints "Sum: " + sum. The constructor part is left out.
public static void main(java.lang.String[]);
Code:
0: iconst_2
1: istore_1
2: iconst_3
3: istore_2
4: iload_1
5: iload_2
6: invokestatic #7 // Method add:(II)I
9: istore_3
10: getstatic #13 // Field java/lang/System.out:Ljava/io/PrintStream;
13: iload_3
14: invokedynamic #19, 0 // InvokeDynamic #0:makeConcatWithConstants:(I)Ljava/lang/String;
19: invokevirtual #23 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: returnBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Run a class file that is newer than your JVM
Compile with JDK 21 (javac Main.java), then run the class with an old Java 8 runtime.
Myth vs fact
Myth
Java is slow because it is interpreted.
Fact
The JVM interprets bytecode only at first. Code that runs often is compiled to optimised machine code by the JIT compiler, and long-running Java services often match C++ speed for typical server work. Start-up is slower, which is a separate issue (Topic 0.8).
Myth
Java and JavaScript are the same language, or one is a lighter version of the other.
Fact
They are unrelated languages that share a name for historical marketing reasons.
Myth
I need to install a JRE to run Java and a JDK to write it.
Fact
Modern Java is installed as a JDK. It runs programs too. Separate JRE downloads stopped with Java 11; apps that need a small runtime build one with jlink.
Myth
Write once, run anywhere means my program behaves identically everywhere, no matter what.
Fact
The language and bytecode behave identically. Things outside the JVM still differ: file paths (C:\Users vs /home), line endings, installed fonts, default character encoding before Java 18, and the time zone. Good Java code avoids relying on them.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Every class file starts with the magic bytes
0xCAFEBABE, then a minor and major version. Major version = Java version + 44, so Java 8 is 52, Java 11 is 55, Java 17 is 61, Java 21 is 65 and Java 25 is 69.javap -v Main | grep majorshows it. - ▸
Bytecode is typed and stack-based, about 200 opcodes. Since Java 7 there is
invokedynamic, which lets the JVM link a call site at run time.javacuses it for lambdas (Java 8) and, since Java 9, for string concatenation (makeConcatWithConstantsin the javap output above) so the JVM can pick the fastest strategy without recompiling your code. - ▸
JDK vs JRE matters in containers: a full JDK image is several hundred megabytes.
jdeps --print-module-depsfinds the modules your app uses, andjlink --add-modules ... --output rtbuilds a runtime with only those, often under 60 MB (see the Docker course for multi-stage builds). - ▸
The JVM is a specification (JVMS) with several implementations. HotSpot is the default in OpenJDK builds; OpenJ9 trades some peak speed for lower memory; GraalVM adds the Graal JIT and Native Image, which compiles ahead of time to a standalone executable with fast start-up but a closed-world limit on reflection.
Remember this
- 1
Java is two things. Java the language is the set of words and grammar rules you write (
class,if,int...), defined by the Java Language Specification. Java the platform is everything that runs your code: the JVM plus a large standard library of ready-made code for text, maths, files, networking, collections and more. - 2
The compiler
javacreads your source fileMain.java, checks it against the language rules, and writesMain.class. That file holds bytecode: compact instructions for an imaginary computer, the same on every operating system. It is not machine code for your real CPU. - 3
The JVM (Java Virtual Machine) is a program that pretends to be that imaginary computer. You start it with the
javacommand. It loads.classfiles, checks them for safety, runs the bytecode, and translates frequently used parts into real machine code for the CPU it is on (Topic 0.8). There is a different JVM build for each operating system and chip, but they all run the same bytecode. This is Java's famous promise: write once, run anywhere. - 4
The JDK (Java Development Kit) is what you install to write Java. It contains a JVM, the standard library, and the developer tools:
javac(compiler),java(launcher),jshell(try code interactively, Topic 0.6),jar(package classes),javadoc(documentation),javap(look inside class files) and diagnostic tools such asjcmd. The JRE (Java Runtime Environment) was the smaller package with only the JVM and library, for people who just run Java programs. Since Java 11 no separate JRE is published by Oracle; you install a JDK, or build a trimmed runtime for your app withjlink. - 5
The JVM manages memory for you. When you create objects, the JVM finds space for them, and a garbage collector frees that space once nothing uses the objects any more. You never free memory by hand, which removes a whole family of crashes common in languages like C. You'll see how in Topic 3.11 (stack and heap) and Topic 14.3 (garbage collection).
- 6
OpenJDK is the open-source project where Java itself is built. Companies take its code and publish ready-to-install JDKs called distributions: Eclipse Temurin, Oracle JDK, Amazon Corretto, Azul Zulu, Microsoft Build of OpenJDK and others. They are built from almost the same source and behave the same for your programs. This course recommends Eclipse Temurin because it is free and open source (Topic 0.4).
- 7
Java is not JavaScript. The names are similar for marketing reasons from 1995, but they are different languages with different rules. Java is statically typed (every variable has a fixed type checked before the program runs), object-oriented (programs are built from classes and objects, Phase 4) and garbage-collected. It runs banking systems, Android apps (through Android's own runtime), big-data tools like Kafka and Hadoop, and games like Minecraft: Java Edition.
Explain it without notes
Explain the difference between the JDK, the JRE and the JVM.
What is bytecode, and why doesn't Java compile straight to machine code?
How does Java achieve "write once, run anywhere", and where does that promise stop?
What is OpenJDK, and why are there several JDK distributions?
Practice
Write a program with two classes in one file: a Calculator class with a method that doubles a number, and Main, which prints the double of 21.
Write a program that uses Math.max, Math.min and Math.abs from the standard library and prints the results for 8 and -3.
Write a program that prints Integer.MAX_VALUE and Long.MAX_VALUE, each on its own line.
Trade-offs
- ↔
Bytecode plus a JVM buys portability, safety checks and run-time optimisation, at the cost of start-up time and memory for the JVM itself. Ahead-of-time compilation (GraalVM Native Image) flips that trade: fast start, small memory, but a longer build and limits on dynamic features.
- ↔
Automatic garbage collection removes whole classes of memory bugs, but the collector uses CPU and can pause the program briefly. Modern collectors (G1, ZGC) keep pauses short; Topic 14.3 covers tuning.
- ↔
Picking a distribution is about support, not features: a vendor with long-term updates for your Java version matters more than the brand name.
Done when you can
Done when you can explain JDK, JRE and JVM with the nested-boxes picture.
Done when you can say what
javacproduces and what thejavacommand does with it.Done when you can explain bytecode with the sheet-music analogy and say why it makes Java portable.
Done when you can name two JDK distributions and say why they behave the same.
Done when you can explain why a class compiled with Java 21 fails on Java 8.