Java Module 1 – Start here: JDK 25 LTS and your first programs
What Java is, how it runs and where it is used
How a Java program runs, from javac and bytecode to the JVM and its JIT compiler, what JDK 25 LTS means, and where Java runs today, Android included.
What you will learn
- Explain how javac, bytecode and the JVM turn a source file into a running program
- Predict whether a JVM will run a class file from the class file's version
- Distinguish Java SE, OpenJDK, a JDK and the JVM
- Describe the six-month release cadence and why this track uses JDK 25 LTS
- Identify where Java code runs today, from servers and build tools to Android on ART
What you’ll learn
What you will learn
- Explain how javac, bytecode and the JVM turn a source file into a running program
- Predict whether a JVM will run a class file from the class file's version
- Distinguish Java SE, OpenJDK, a JDK and the JVM
- Describe the six-month release cadence and why this track uses JDK 25 LTS
- Identify where Java code runs today, from servers and build tools to Android on ART
On this page
Java is a general-purpose programming language and also the platform that runs it. A Java program is compiled once,
and the result runs unchanged on Windows, macOS and Linux, on Intel and Arm: in this lesson one compiled file,
Hello.class, runs on JDK 25 and on JDK 27, and JDK 21 refuses it with an error you will learn to read. The compiler,
javac, translates the .java text you write into bytecode: The instructions that javac writes into class files: the instruction set of the Java Virtual Machine, a computer that exists only as a specification, so the same bytecode runs on any system that has a recent enough JVM., and a
JVM: The Java Virtual Machine: the runtime that loads class files, verifies their bytecode and runs it, interpreting at first and compiling methods that run often to machine code. In OpenJDK builds it is HotSpot. (JVM) runs that bytecode on your real processor.
The language is statically typed (the compiler checks the type of every value before anything runs) and object-oriented, and a garbage collector frees memory that the program no longer uses. Java runs back-end services, data and messaging systems, build tools and desktop applications, and Android apps are written in it too. This track teaches JDK: The Java Development Kit: a JVM, the standard library and the tools for writing Java, among them the compiler javac, the java launcher, the disassembler javap and JShell. 25, the current LTS release: A long-term support release: one feature release every two years (8, 11, 17, 21 and 25 so far, with 29 planned) that vendors keep updating for years. Eclipse Adoptium supports each one for at least four years., and its examples run on Eclipse Temurin 25.0.4.1.
javac compiles your source into bytecode once
Java separates writing a program from running it. Here is the shortest kind of Java program, a compact source file. Lesson 3 explains every part of it; for now it is enough to see that it prints a greeting and the version of Java that runs it:
void main() {
IO.println("Hello from Java " + Runtime.version().feature());
} The session below compiles the file, looks at what the compiler produced and runs the result. Every session in this track is read the same way:
How to read the examples
Each example shows its Java file first and then a session: the commands it runs, listed in a short script, and under
them the output, where every command appears after $ followed by what it printed (standard output and error
together, as a terminal shows them). The sessions were recorded on a Mac with Apple silicon (macOS 26) with Eclipse
Temurin 25.0.4.1. When a session compares JDKs, a line that starts with # JDK in use: names the JDK that runs the
commands after it. Once lesson 2 has installed a JDK, you can type the same commands in your own terminal.
from session import run
# Compile Hello.java into the folder out, look at the class file it produced, then run it.
run("""
javac -d out Hello.java
find out -type f
xxd -l 8 out/Hello.class
javap -v out/Hello.class | grep -E "(minor|major) version"
java -cp out Hello
""") Output
# JDK in use: openjdk version "25.0.4.1" LTS $ javac -d out Hello.java $ find out -type f out/Hello.class $ xxd -l 8 out/Hello.class 00000000: cafe babe 0000 0045 .......E $ javap -v out/Hello.class | grep -E "(minor|major) version" minor version: 0 major version: 69 $ java -cp out Hello Hello from Java 25
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 bytecode_session.py
Line by line:
javac -d out Hello.javaprinted nothing, which is how the compiler reports success. The-d outoption tells it to write the class files into a folder namedout.findlists the result, one file:out/Hello.class. That class file: The .class file that javac writes for each class: its bytecode and constants, starting with the bytes CA FE BA BE and a version number, 69 for Java 25. A JVM runs class files of its own version and older ones. is the compiled program; the.javafile is not needed to run it.xxdshows the first eight bytes of the class file in hexadecimal. Every class file begins with the same four bytes,cafe babe, followed by two version numbers of two bytes each: the minor version, 0, and the major version,0x45, which is 69 in decimal.javap -v(the JDK’s class file disassembler) prints the same two numbers. Major version 69 means a class file for Java 25.java -cp out Hellostarts a JVM, looks for the classHelloon the class pathoutand runs it.
Bytecode is the instruction set of a computer that exists only as a specification, so the class file says nothing
about the operating system or the processor it was compiled on. The figure puts the two steps in order: javac
runs once, and the JVM runs the class file every time the program runs.
From a source file to running code
Text description of the diagram
The diagram shows the two steps of running a Java program, from top to bottom.
- javac, the compiler, reads the source code in Hello.java and writes the class file Hello.class, which holds bytecode. Its class file version is 69, the version of Java 25. A compile error stops the program at this step, before anything runs.
- The java command starts a Java Virtual Machine (JVM). Inside it, the class loader finds and reads Hello.class; a class file newer than the JVM stops the program here. Linking then verifies the bytecode and prepares the class. Finally the bytecode is executed: the interpreter runs it, and the JIT compiler turns methods that run often into machine code, which your processor runs directly.
Checkpoint
Check: javac, bytecode and class files
The JVM loads, verifies and initialises a class before main runs
Before the first line of main runs, the JVM does three things, in this order. Its class loader finds Hello.class
and reads it. Linking then verifies the bytecode, checking that it is well formed and cannot break the JVM’s rules,
and prepares the class in memory. Last, the class is initialised, which runs any static initialisers it declares. Only
then is main called. Step through the run of java -cp out Hello from the session above:
The drawing shows the whole scene; its 6 steps are listed below.
Every step as text
- Start a JVM. java -cp out Hello starts a JVM and tells it two things: the class to run, Hello, and where to look for classes, the class path out.
- Load the class. The class loader finds out/Hello.class and reads it. Its version, 69, is one that a JDK 25 JVM accepts. A class file newer than the JVM would stop the program here, before any of its code runs.
- Link it. Linking verifies the bytecode, checking that it is well formed and cannot break the JVM's rules, and then prepares the class in memory.
- Initialise it. Initialisation runs the static initialisers that the class declares. Hello declares none, so nothing visible happens in this step.
- Call main. Only now is main called. Hello's main is an instance method of a compact source file, so the launcher first creates an object of the class and then calls main on it.
- Run it. The interpreter starts on main's bytecode at once. Methods that run often are compiled to machine code while the program runs, which the next section measures.
Two stops on this route are worth knowing from the start: a compile error stops the program at javac, before any
class file exists, and a class file that is newer than the JVM stops it while the class is loaded, as a later section
shows. Every other class goes through the same steps, at the latest when the program first needs it; many classes of
the JDK itself are loaded while the JVM starts.
Key idea
The JVM loads a class, links it (verifying its bytecode) and initialises it, and only then calls main.
Checkpoint
Check: What the JVM does before main
The JVM interprets first and compiles hot methods
A JVM could interpret bytecode one instruction at a time for as long as a program runs, but that would be slow.
HotSpot, the JVM in OpenJDK builds, starts with its interpreter, notices which methods run often and compiles those
hot methods to native machine code while the program is running. This is
JIT compilation: Just-in-time compilation: while a program runs, the JVM compiles the methods that run often from bytecode to native machine code, so a Java program gets faster after a short warm-up. The option -Xint switches it off.. The java documentation describes it as the
default: the interpreter runs all bytecode except hot methods, which are compiled to native code, and java -version
calls this mixed mode. The option -Xint switches the JIT compiler off. This program adds up the digits of every
number from 1 to 20 million and times the work:
// Adds up the digits of every number from 1 to 20 million: plain arithmetic in a loop, timed.
long digitSum(int limit) {
long total = 0;
for (int n = 1; n <= limit; n++) {
for (int rest = n; rest > 0; rest /= 10) {
total += rest % 10;
}
}
return total;
}
void main() {
long start = System.nanoTime();
long total = digitSum(20_000_000);
long millis = (System.nanoTime() - start) / 1_000_000;
IO.println("digit sum: " + total);
IO.println("time: " + millis + " ms");
} from session import run
# The same class file twice: in the default mixed mode (interpreter and JIT compiler), then interpreted only.
run("""
javac -d out Busy.java
java -cp out Busy
java -Xint -cp out Busy
java -version 2>&1 | tail -n 1
java -Xint -version 2>&1 | tail -n 1
""") Output
# JDK in use: openjdk version "25.0.4.1" LTS $ javac -d out Busy.java $ java -cp out Busy digit sum: 640000002 time: 233 ms $ java -Xint -cp out Busy digit sum: 640000002 time: 2272 ms $ java -version 2>&1 | tail -n 1 OpenJDK 64-Bit Server VM Temurin-25.0.4.1+1 (build 25.0.4.1+1-LTS, mixed mode, sharing) $ java -Xint -version 2>&1 | tail -n 1 OpenJDK 64-Bit Server VM Temurin-25.0.4.1+1 (build 25.0.4.1+1-LTS, interpreted mode, sharing)
This output changes from run to run: The two timings depend on the computer and on what else it was doing; the digit sum and the two modes are the same on every run.
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 jit_session.py
Both runs computed the same digit sum from the same bytecode. On the computer that recorded this session, the run
without the JIT compiler took several times as long. The last two commands show where the mode appears: the third line
of java -version says mixed mode, or interpreted mode under -Xint. You never call the JIT compiler yourself, but
it explains two habits of experienced Java developers: they expect a program to get faster after a short warm-up, and
they never trust a single cold timing of a piece of code.
Checkpoint
Check: The interpreter and the JIT compiler
A JVM runs older class files and refuses newer ones
The class file version works in one direction only. A JVM runs class files of its own version and of every earlier
version, so a library compiled years ago for Java 8 still runs on Java 25. It refuses a class file that is newer than
itself, because such a file may use instructions or library methods that the older JVM does not have. Here the same
Hello.class, compiled once with JDK 25, runs on a newer JDK and then on an older one:
from session import run
# Compile once, with JDK 25, then run the same class file on a newer and on an older JVM.
run("""
javac -d out Hello.java
java -cp out Hello
""")
run("java -cp out Hello", jdk="27")
run("java -cp out Hello", jdk="21", expect_failure=["java -cp out Hello"]) Output
# JDK in use: openjdk version "25.0.4.1" LTS $ javac -d out Hello.java $ java -cp out Hello Hello from Java 25 # JDK in use: openjdk version "27" $ java -cp out Hello Hello from Java 27 # JDK in use: openjdk version "21.0.12.1" LTS $ java -cp out Hello Error: LinkageError occurred while loading main class Hello java.lang.UnsupportedClassVersionError: Hello has been compiled by a more recent version of the Java Runtime (class file version 69.0), this version of the Java Runtime only recognizes class file versions up to 65.0 [exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 older_newer_session.py
Step through the three runs, with the version numbers that each JVM reported:
The drawing shows the whole scene; its 5 steps are listed below.
Every step as text
- Compile once. The javac of JDK 25 wrote Hello.class with class file version 69, the version of Java 25. All three runs use this one file.
- On JDK 25. Temurin 25 accepts class files up to version 69, its own, so it runs the class, which prints Hello from Java 25.
- On JDK 27. Temurin 27 is newer than the class file, so version 69 is within what it accepts. The bytecode is the same, but it asks the running JVM for its version, so this time it prints Hello from Java 27.
- On JDK 21. Temurin 21 recognises class file versions up to 65.0, and this file is 69.0. It stops with UnsupportedClassVersionError before a single line of the program runs.
- Two cures. Run the program on JDK 25 or a later JDK, or compile it for the older release with javac --release, which lesson 5 shows.
Temurin 27 ran the class unchanged, and the program printed Java 27: the bytecode is identical, but it asks the JVM
that is running it for its version. Temurin 21 stopped before running a single line, with an
UnsupportedClassVersionError that names both numbers: the class file is version 69.0, and a Java 21 JVM recognises
versions up to 65.0. The cure is either to run the program on JDK 25 or later, or to compile it for the older release,
which lesson 5 shows.
Key idea
A JVM runs class files of its own version and older, and refuses newer ones before any code runs.
Checkpoint
Check: Class file versions
Java SE is a specification, and a JDK is one build of it
Four names come up all the time, and each means something different:
- Java SE is the specification of the platform. The Java Language Specification (JLS) defines the language, the Java Virtual Machine Specification (JVMS) defines class files and the JVM, and the API documentation defines the standard library. Each version is defined through the Java Community Process.
- OpenJDK is the open-source project whose JDK releases are the reference implementation of each Java SE version, such as JDK 25 for Java SE 25.
- A JDK, Java Development Kit, is what you install: a JVM, the standard library and the tools, among them
javac,java,javapandjshell. - The JVM is the runtime inside a JDK that loads class files and runs them; in OpenJDK builds it is HotSpot.
Step through how the four fit together, with the builds this track uses:
The drawing shows the whole scene; its 5 steps are listed below.
Every step as text
- The specification. Java SE 25 is the specification of the platform. The Java Language Specification defines the language, the Java Virtual Machine Specification defines class files and the JVM, and the API documentation defines the standard library.
- The reference implementation. OpenJDK is the open-source project whose JDK 25 is the reference implementation of Java SE 25.
- The vendors' builds. Vendors build JDKs from the OpenJDK source code and publish update releases for them. Eclipse Adoptium's builds are called Temurin; Oracle, Microsoft, Azul and Red Hat publish builds too, and a program behaves the same on any of them.
- The JDK you install. A JDK, Java Development Kit, is what you install. It holds a JVM, the standard library and the tools, among them javac, java, javap and jshell. This track's examples run on Temurin 25.0.4.1.
- The JVM inside it. The JVM is the runtime inside a JDK that loads class files and runs them; in OpenJDK builds it is HotSpot. A JRE, which some vendors offer, has a runtime but no compiler, so it runs Java programs but cannot build them.
Several vendors build JDKs from the OpenJDK source code and publish update releases for them: Eclipse Adoptium (whose builds are called Temurin), Oracle, Microsoft, Azul and Red Hat, among others. A program behaves the same on any of them. They differ in their licence terms, in how long each release receives updates and in the platforms they cover, which is how you choose one in lesson 2. Some vendors also offer a smaller package without the compiler, a Java Runtime Environment (JRE), for machines that only run Java programs. To write Java you need a full JDK.
A program can ask the JVM which build is running it:
// Asks the running JVM which Java it is.
void main() {
Runtime.Version version = Runtime.version();
IO.println("Java version: " + version);
IO.println("Feature release: " + version.feature());
IO.println("Vendor: " + System.getProperty("java.vendor"));
IO.println("Virtual machine: " + System.getProperty("java.vm.name"));
IO.println("Class files up to: " + System.getProperty("java.class.version"));
IO.println("Operating system: " + System.getProperty("os.name") + " on " + System.getProperty("os.arch"));
} from session import run
run("java WhichJava.java") Output
# JDK in use: openjdk version "25.0.4.1" LTS $ java WhichJava.java Java version: 25.0.4.1+1-LTS Feature release: 25 Vendor: Eclipse Adoptium Virtual machine: OpenJDK 64-Bit Server VM Class files up to: 69.0 Operating system: Mac OS X on aarch64
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 which_java_session.py
25.0.4.1+1-LTS names the exact build (lesson 2 takes the version string apart), Eclipse Adoptium is the vendor, and
69.0 is the newest class file version this JVM accepts, the same number that javap showed above.
Checkpoint
Check: Java SE, OpenJDK, a JDK and the JVM
A feature release every six months, an LTS every two years
New Java versions arrive on a timetable instead of waiting for features. OpenJDK ships a feature release: A new Java version with new features, shipped every six months, in March and September, such as JDK 26 and JDK 27. A release without long-term support stops receiving updates once the next one is out. every six months, in March and September, and each has its own number: 25, 26 and 27 are the latest three, and 27 is the current one. Between feature releases, update releases fix bugs and security problems four times a year, usually on the third Tuesday of January, April, July and October. When an urgent security fix cannot wait, an extra update appears between them, with four numbers in its version: Temurin 25.0.4.1 is one of those.
Every two years, one feature release is designated long-term support (LTS). Oracle’s support roadmap lists 8, 11, 17, 21 and 25 as LTS releases and plans 29 as the next one. The difference lies in how long updates continue. A release without LTS stops receiving updates once the next feature release is out: Adoptium’s roadmap, for example, ends the availability of Temurin 26 when Temurin 27 arrives. An LTS release keeps receiving updates for years: Adoptium supports each LTS for at least four years and lists Temurin 25 until at least 2031. Walk through the recent releases and what each one brought:
- 8, 11 and 17
The earlier LTS releases LTS
Oracle's support roadmap lists 8, 11 and 17 as LTS releases. Their class files still run on the newest JVMs, because a JVM runs class files of every earlier version.
- JDK 21
Virtual threads and record patterns LTS
An LTS release. It brought virtual threads, record patterns, pattern matching for switch and sequenced collections. A JDK 21 JVM accepts class files up to version 65, so it refuses this lesson's Hello.class.
- JDK 25
Compact source files become final LTS, this track
The LTS release this track uses. It made compact source files and instance main methods permanent, and added module import declarations, flexible constructor bodies and scoped values. Adoptium lists Temurin 25 until at least 2031.
- JDK 26
HTTP/3 in the HTTP client feature release
A feature release. It added HTTP/3 to the HTTP client and a second preview of lazy constants. Without long-term support, it stops receiving updates once the next feature release is out.
- JDK 27
G1 by default in every environment current
The current feature release. G1 became the default garbage collector in every environment, and compact object headers are now on by default.
- JDK 28
Value objects, as a preview in development
In development. Value objects, as a preview, are among the JEPs targeted to it so far.
- JDK 29
The next LTS release planned LTS
Oracle's support roadmap plans JDK 29 as the next LTS release, four feature releases after JDK 25.
The timeline has 7 events, from 8, 11 and 17 to JDK 29.
A JEP: A JDK Enhancement Proposal: the document that describes one change to the JDK, with its type, scope, status and the release that delivers it, at openjdk.org/jeps/ followed by its number. More in “Java versions, LTS and preview features”, JDK Enhancement Proposal, is the document that describes one change to the JDK; every
feature on that timeline has one, and lesson 5 shows how to read them. This track uses JDK 25 for two reasons. An LTS
release is what many teams, courses and tools settle on, because it keeps receiving updates for years. And JDK 25 is the
release in which the short form of Hello.java stopped being a preview feature and became a permanent part of Java.
When a lesson uses something that became final only in JDK 26 or 27, or that is still a preview, it carries a version
label, which lesson 5 explains.
Key idea
A feature release ships every six months and is updated until the next one; every two years one of them is an LTS release, updated for years, and JDK 25 is the LTS release this track uses.
Checkpoint
Check: Feature releases and LTS releases
Java runs on servers, in tools and on desktops, and on Android through ART
Java runs in more places than you might expect, and not always on a JVM:
- Back-end services. Web and business applications are built with frameworks such as Spring Boot, whose current version (4.1.1) needs at least Java 17, and with Jakarta EE, which the later modules of this track cover.
- Data and messaging systems. Apache Kafka, the event-streaming platform, needs Java 17 or later to run.
- Developer tools. Build tools are Java programs themselves: Gradle needs JDK 17 or newer to run, and Maven needs a JDK installed.
- Android apps. They are written in Java or Kotlin and built on a computer with a JDK, but Android’s documentation
is plain that the JVM “is not used on Android devices or emulators”. The build tool
d8compiles the Java bytecode into DEX bytecode, and the phone runs that on ART, the Android runtime. Android’s own table of Java versions ends at Java 17, for Android 14 (API level 34), so lessons about newer Java features carry a note for Android developers. - Desktop applications. JavaFX builds desktop interfaces (module 18 of this track), and older applications use Swing.
The Android route is the one that surprises most people. Step through it from the source code to the phone:
The drawing shows the whole scene; its 5 steps are listed below.
Every step as text
- Write it. An Android app is written in Java or Kotlin, and it is built on a computer that has a JDK installed.
- Compile it. The build compiles the Java source to bytecode in class files, the same format as in the rest of this lesson.
- Convert it. The build tool d8 compiles that Java bytecode into DEX bytecode, the format that Android runs.
- Run it on ART. The phone runs the DEX bytecode on ART, the Android runtime. Android's documentation says that the JVM is not used on Android devices or emulators.
- Java versions. Android's own table of Java versions ends at Java 17, for Android 14 (API level 34), so lessons about newer Java features carry a note for Android developers.
A JDK is needed only on the computer that builds the app: the phone never receives a class file, only the DEX bytecode that ART runs.
Checkpoint
Check: Where Java runs
Practise: name a release
Write the body of describe so that it returns "Java 25 (LTS)" for a release in the set LTS, and
"Java 27 (feature release)" for any other. The set and three checks are already in the file. Save it, run
java Describe.java with JDK 25, and edit until every line says PASS.
// Exercise: label a Java version as an LTS release or a feature release.
// Write the body of describe, then run: java Describe.java
final Set<Integer> LTS = Set.of(8, 11, 17, 21, 25);
String describe(Runtime.Version version) {
// Return "Java 25 (LTS)" for a release in LTS, otherwise "Java 27 (feature release)".
return "";
}
void check(String text, String expected) {
String got = describe(Runtime.Version.parse(text));
String verdict = got.equals(expected) ? "PASS" : "FAIL";
IO.println(verdict + " " + text + " -> \"" + got + "\" (expected \"" + expected + "\")");
}
void main() {
check("25.0.4.1+1", "Java 25 (LTS)");
check("27+35", "Java 27 (feature release)");
check("21.0.12", "Java 21 (LTS)");
} As given, describe returns an empty string, so all three checks fail:
from session import run
# The exercise as given: describe returns an empty string, so every check fails.
run("java Describe.java") Output
# JDK in use: openjdk version "25.0.4.1" LTS $ java Describe.java FAIL 25.0.4.1+1 -> "" (expected "Java 25 (LTS)") FAIL 27+35 -> "" (expected "Java 27 (feature release)") FAIL 21.0.12 -> "" (expected "Java 21 (LTS)")
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 describe_session.py
First hint: version.feature() returns the first number of a version (25 for 25.0.4.1+1), and
LTS.contains(...) tells you whether a number is in the set. Join the pieces with +, as Hello.java does.
A set of LTS numbers written into the code has to be updated by hand: when JDK 29 ships as the next LTS, it needs one more number.
Each session of this lesson is recorded by a short Python script, session.py, which hands every command to the shell
and prints what it printed. It also leaves out the release date that java -version prints after the version number.
If you want to replay a session exactly, save this file next to the lesson’s files:
"""Runs shell commands the way a terminal shows them, and prints the session.
Each line of the script is one command. The session prints it after "$ ", then what it printed: standard output
and standard error together, as a terminal shows them. A command that ends with a status other than 0 is followed
by "[exit status N]"; unless the script lists that command in expect_failure, the session then fails too, so a
failure nobody expected stops it. A line that starts with "#" is printed as a comment.
`java`, `javac` and `javap` belong to the JDK named by `jdk`, which comes first on PATH: "25" is Eclipse Temurin
25.0.4.1, the JDK of this track, and "21" and "27" are Temurin 21.0.12.1 and Temurin 27, for comparisons. They are
the JDKs of the mise installation that also holds the Python running this file. `java -version` prints the build's
release date after the version number; the session leaves the date out. To replay a session on your own computer,
point JDKS at the bin folders of your JDKs, or type the commands yourself.
"""
import os
import re
import subprocess
import sys
from pathlib import Path
# <mise>/installs/python/3.14.8/bin/python3 -> <mise>/installs
INSTALLS = Path(sys.executable).resolve().parents[3]
JDKS = {
"25": INSTALLS / "java" / "temurin-25.0.4+101.0.LTS" / "bin",
"21": INSTALLS / "java" / "temurin-21.0.12+101.0.LTS" / "bin",
"27": INSTALLS / "java" / "temurin-27.0.0+35" / "bin",
}
# 'openjdk version "25.0.4.1" YYYY-MM-DD LTS' and 'openjdk 25.0.4.1 YYYY-MM-DD LTS': the build's release date, YYYY-MM-DD.
RELEASE_DATE = re.compile(r'(?m)^((?:openjdk|java)(?: version)? "?[0-9][\w.+-]*"?) \d{4}-\d{2}-\d{2}')
def _tidy(text):
"""The output as the page shows it: no release dates, and mise's folder written the way mise documents it."""
return RELEASE_DATE.sub(r"\1", text).replace(str(INSTALLS), "~/.local/share/mise/installs")
def _shell(command, jdk):
env = dict(os.environ, PATH=os.pathsep.join([str(JDKS[jdk]), os.environ.get("PATH", "")]))
return subprocess.run(command, shell=True, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
def run(script, jdk="25", expect_failure=()):
"""Runs each line of the script as one shell command in the examples folder, with JDK `jdk` first on PATH."""
first = _shell("java -version", jdk)
if first.returncode != 0 or not first.stdout:
sys.exit(f"JDK {jdk} is not installed on this computer ({JDKS[jdk]})")
print("# JDK in use:", _tidy(first.stdout.splitlines()[0]))
unexpected = 0
for line in script.strip().splitlines():
command = line.strip()
if not command:
continue
if command.startswith("#"):
print(command)
continue
print(f"$ {command}")
done = _shell(command, jdk)
print(_tidy(done.stdout), end="")
if done.returncode != 0:
print(f"[exit status {done.returncode}]")
if command not in expect_failure:
unexpected += 1
if unexpected:
sys.exit(1) The self-check below has questions on all seven ideas of this lesson. It starts with the one you know least and explains every answer as soon as you give it:
Practice that adapts to you
Practise this lesson
17 questions about 7 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.
Interview questions
Fresher · What are the JDK, the JRE and the JVM, and which one do you install to write Java?
The JVM (Java Virtual Machine) is the runtime that loads class files, verifies their bytecode and runs it, interpreting
at first and compiling hot methods to machine code with its JIT compiler. A JRE (Java Runtime Environment) is a JVM plus
the standard library: enough to run Java programs, not to build them. The JDK (Java Development Kit) contains a full
runtime and the development tools, such as the compiler javac, the java launcher, the disassembler javap and
JShell. To write Java you install a JDK. A complete answer also names what sits behind them: Java SE specifies the
language, the class file format and the API, and the JDKs of different vendors are builds of OpenJDK, the reference
implementation, so one class file runs on any of them.
Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.
-
Fresher to mid
Between "java -cp app.jar com.shop.Main" and the first line of main, a JVM can fail with ClassNotFoundException, UnsupportedClassVersionError, VerifyError or ExceptionInInitializerError. Walk through what the JVM does at start-up, place each error in its phase, and say what you would check first for each.
-
Mid to senior
After every deploy, a Java service answers its first few hundred requests three to five times slower than usual, then settles. Explain the likely causes, how you would confirm them before changing anything, and which fixes you would consider.
Key takeaways
javaccompiles.javasource into.classfiles of bytecode once, and the JVM runs those class files every time the program runs.- Before
mainruns, the JVM loads the class, links it, which verifies its bytecode, and initialises it. - The JVM interprets bytecode first and compiles hot methods to machine code with its JIT compiler (mixed mode), so a program gets faster after a warm-up.
- A class file records its version, 69 for Java 25, and a JVM runs class files up to its own version and refuses newer
ones with
UnsupportedClassVersionError. - Java SE is the specification, OpenJDK its reference implementation, and a JDK an installable build from a vendor such as Eclipse Adoptium (Temurin) or Oracle; a feature release ships every six months and an LTS every two years.
- Java runs back ends, data systems, build tools and desktop applications, while Android apps are built with Java but run on ART, with Java language support up to Java 17.
Terms in this lesson
- bytecode
- The instructions that javac writes into class files: the instruction set of the Java Virtual Machine, a computer that exists only as a specification, so the same bytecode runs on any system that has a recent enough JVM.
- class file
- The .class file that javac writes for each class: its bytecode and constants, starting with the bytes CA FE BA BE and a version number, 69 for Java 25. A JVM runs class files of its own version and older ones.
- feature release
- A new Java version with new features, shipped every six months, in March and September, such as JDK 26 and JDK 27. A release without long-term support stops receiving updates once the next one is out.
- Java SE
- Java Platform, Standard Edition: the specification of the language (the JLS), of class files and the JVM (the JVMS) and of the standard API, one version for every feature release, such as Java SE 25.
- JDK
- The Java Development Kit: a JVM, the standard library and the tools for writing Java, among them the compiler javac, the java launcher, the disassembler javap and JShell.
- JIT compilation
- Just-in-time compilation: while a program runs, the JVM compiles the methods that run often from bytecode to native machine code, so a Java program gets faster after a short warm-up. The option -Xint switches it off.
- JVM
- The Java Virtual Machine: the runtime that loads class files, verifies their bytecode and runs it, interpreting at first and compiling methods that run often to machine code. In OpenJDK builds it is HotSpot.
- LTS release
- A long-term support release: one feature release every two years (8, 11, 17, 21 and 25 so far, with 29 planned) that vendors keep updating for years. Eclipse Adoptium supports each one for at least four years.
- OpenJDK
- The open-source project whose JDK releases are the reference implementation of each Java SE version. Eclipse Adoptium (Temurin), Oracle and other vendors build their JDKs from its source code.
References
- The Java Virtual Machine Specification, Java SE 25: Chapter 4, The class File Format (Oracle)
- The Java Language Specification, Java SE 25: Chapter 12, Execution (Oracle)
- The java Command (JDK 25 tool reference) (Oracle)
- The javap Command (JDK 25 tool reference) (Oracle)
- Java Virtual Machine Technology Overview (JDK 25) (Oracle)
- JDK 21 (OpenJDK)
- JDK 25 (OpenJDK)
- JDK 26 (OpenJDK)
- JDK 27 (OpenJDK)
- JDK 28 (OpenJDK)
- Oracle Java SE Support Roadmap (Oracle)
- Temurin Support and Release Roadmap (Eclipse Adoptium)
- Linux (RPM/DEB/APK) installer packages (Temurin JDK and JRE packages) (Eclipse Adoptium)
- Java versions in Android builds (Android Developers)
- d8 (compiles Java bytecode into DEX bytecode) (Android Developers)
- Android runtime and Dalvik (Android Open Source Project)
- Apache Kafka Quickstart (The Apache Software Foundation)
- Installing Gradle (Gradle)
- Installing Apache Maven (The Apache Software Foundation)
- Spring Boot System Requirements (Spring)
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress