Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

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.

  • Beginner
  • 20 minutes
  • Examples run with Java 25.0.4.1 and Python 3.14.8
  • By MySmartCoPilot
Free lesson, Pro answers: 20 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

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:

Hello.java: a whole program Java · Hello.java
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.

Compile, inspect and run Python · bytecode_session.py
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.java printed nothing, which is how the compiler reports success. The -d out option tells it to write the class files into a folder named out.
  • find lists 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 .java file is not needed to run it.
  • xxd shows 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 Hello starts a JVM, looks for the class Hello on the class path out and 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.

Running a Java program: javac compiles Hello.java to the class file Hello.class, and the JVM loads, links and runs its bytecode.Hello.javasource codejavac, the compilercompile errors stop hereHello.classbytecode, class file version 69The JVM (the java command)Your processorruns machine codeClass loaderfinds and reads the class file;a class file that is too new stops hereLinkingverifies the bytecode, prepares the classExecutioninterpreter, plus the JIT compilerfor hot methods1. javac -d out Hello.java2. java -cp out Hello

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.

  1. 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.
  2. 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.
Hex Viewer & File Inspector Open a .class file of your own and find the bytes CA FE BA BE and the version that follows them.

Checkpoint

Check: javac, bytecode and class files

  1. Question 1 of 2 After javac -d out Hello.java, which file does java -cp out Hello need in order to run the program?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: out/Hello.class

    javac reads Hello.java once and writes out/Hello.class. From then on, java -cp out Hello loads that class file and runs its bytecode; the source file could be deleted.

  2. Question 2 of 2 Another class file begins with the bytes cafe babe 0000 0041. Its major version is the hexadecimal number 0x41. What is that in decimal?

    Type a number.

    A hint

    0x45 was 4 × 16 + 5 = 69. Do the same with 0x41.

    Show the answer: Question 2 of 2

    Answer: 65

    0x41 is 4 × 16 + 1 = 65, the class file version of Java 21. The session's Hello.class had 0x45, 4 × 16 + 5 = 69, the version of Java 25. The two bytes before it, 0000, are the minor version, 0.

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:

Interactive · stage by stage What the JVM does with Hello.class before main runs Step through java -cp out Hello from the session above, from the start of the JVM to the line that main prints.
What the JVM does with Hello.class before main runs, step 6 of 6. Showing java -cp out Hello, Load (version 69: accepted), Link, Initialise, Call main (printed: Hello from Java 25), Run the bytecode. In focus: Run the bytecode.java -cp out Hellostarts a JVMLoadversion 69: acceptedLinkverifies and preparesInitialiseruns static initialisersCall mainprinted: Hello from Java 25Run the bytecodeinterpreter, then JIT

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. 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.
  2. 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.
  3. 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.
  4. Initialise it. Initialisation runs the static initialisers that the class declares. Hello declares none, so nothing visible happens in this step.
  5. 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.
  6. 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

  1. Question 1 of 2 In which order does the JVM prepare a class before it calls main?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Load it, link it (verify and prepare), then initialise it

    The class loader finds and reads the class file, linking verifies the bytecode and prepares the class, and initialisation runs its static initialisers. Only then is main called.

  2. Question 2 of 2 A class file is newer than the JVM that is asked to run it. When does the program stop?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: While the class is loaded, before any of its code runs

    Version checking is part of loading, the first of the JVM's steps. The session on JDK 21 shows it: the error appeared while loading the main class, before Hello printed anything.

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:

Busy.java: a timed loop Java · Busy.java
// 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");
}
The same class file with and without the JIT compiler Python · jit_session.py
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

  1. Question 1 of 2 Busy printed digit sum: 640000002 both with and without -Xint, from the same class file. What did -Xint change?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: How the JVM executed the bytecode, by the interpreter alone instead of with the JIT compiler as well

    The same bytecode ran twice. In mixed mode the JVM compiled the hot loop to machine code; under -Xint it interpreted every instruction, which took several times as long and gave the same digit sum.

  2. Question 2 of 2 The last line of java -version ends in mixed mode, sharing). What does mixed mode mean?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: The interpreter runs the bytecode, and the JIT compiler compiles the methods that run often

    Mixed mode is the interpreter together with the JIT compiler: everything starts interpreted, and hot methods are compiled to machine code while the program runs.

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:

One class file on JDK 25, 27 and 21 Python · older_newer_session.py
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:

Interactive · step by step One class file, three JVMs Step through the three runs of the session above. The class file stays the same; only the JVM that reads it changes.
One class file, three JVMs, step 5 of 5. Showing Hello.class, Temurin 25 (printed: Java 25), Temurin 27 (printed: Java 27), Temurin 21 (refused: 69 is too new). In focus: Hello.class, Temurin 21.Hello.classversion 69, from JDK 25Temurin 25printed: Java 25Temurin 27printed: Java 27Temurin 21refused: 69 is too new

The drawing shows the whole scene; its 5 steps are listed below.

Every step as text
  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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

  1. Question 1 of 2 A class file has major version 65, the version that Java 21 writes. Which of these JVMs run it?

    Choose every answer that is right.

    Show the answer: Question 1 of 2

    Answer:

    • Temurin 25
    • Temurin 27
    • Temurin 21

    The rule works in one direction: a JVM runs class files up to its own version. Java 21, 25 and 27 JVMs all accept version 65; a Java 17 JVM, whose own version is 61, refuses it.

  2. Question 2 of 2 The error on JDK 21 named two numbers, class file version 69.0 and class file versions up to 65.0. Which number describes the JVM?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: 65.0, the newest version this JVM recognises

    The first number is the class file's version (69.0, Java 25) and the second is the JVM's limit (65.0, Java 21). Because 69 is above 65, the JVM refused to load the class.

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, javap and jshell.
  • 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:

Interactive · step by step From a specification to the JDK on your computer Step through the four names in order. Each step adds one name and says how it relates to the one before.
From a specification to the JDK on your computer, step 5 of 5. Showing Java SE 25, OpenJDK, Temurin 25.0.4.1, Oracle JDK 25, The JDK you install, The JVM. In focus: The JVM.implemented bybuilt bybuilt bycontainsJava SE 25the specificationOpenJDKreference implementationTemurin 25.0.4.1by Eclipse AdoptiumOracle JDK 25by OracleThe JDK you installJVM, library and toolsThe JVMHotSpot runs your classes

The drawing shows the whole scene; its 5 steps are listed below.

Every step as text
  1. 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.
  2. The reference implementation. OpenJDK is the open-source project whose JDK 25 is the reference implementation of Java SE 25.
  3. 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.
  4. 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.
  5. 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:

WhichJava.java Java · WhichJava.java
// 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"));
}
Which Java is this? Python · which_java_session.py
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

  1. Question 1 of 2 To write and compile Java programs, what do you install?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: A JDK

    A JDK is the installable kit: a JVM, the standard library and the tools, javac among them. Java SE is the specification it implements, and a JRE is a smaller package for machines that only run programs.

  2. Question 2 of 2 The same program runs on Temurin 25 and on Oracle JDK 25. Which of these can differ between the two builds?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: The licence terms, how long updates last and the platforms covered

    Vendors build their JDKs from the same OpenJDK source code for the same specification, so programs behave the same on them. The builds differ in licence terms, update periods and the platforms they cover.

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:

Timeline · 7 events in order Java releases, from the earlier LTS releases to JDK 29 Walk through the releases in order. Each one says what it brought and whether it receives long-term support.
  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. 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

  1. Question 1 of 2 Which release does Oracle's support roadmap plan as the next LTS release after JDK 25?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: JDK 29

    A feature release ships every six months, and every fourth one, every two years, is an LTS release: 21, 25 and then the planned 29.

  2. Question 2 of 2 JDK 27 has been released. Does Adoptium still publish updates of Temurin 26?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: No, because a release without LTS stops receiving updates once the next feature release is out

    A feature release without long-term support is updated for six months, until the next one replaces it. That is why this track uses JDK 25, an LTS release with updates for years.

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 d8 compiles 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:

Interactive · stage by stage How the Java code of an Android app reaches the phone Step through the build from source code to the phone. A JDK is needed only on the computer that builds the app.
How the Java code of an Android app reaches the phone, step 5 of 5. Showing Source code, Compile with a JDK, d8, ART on the phone. In focus: ART on the phone.Source codewritten in Java or KotlinCompile with a JDKbytecode in class filesd8bytecode to DEX bytecodeART on the phoneruns the DEX bytecode

The drawing shows the whole scene; its 5 steps are listed below.

Every step as text
  1. Write it. An Android app is written in Java or Kotlin, and it is built on a computer that has a JDK installed.
  2. Compile it. The build compiles the Java source to bytecode in class files, the same format as in the rest of this lesson.
  3. Convert it. The build tool d8 compiles that Java bytecode into DEX bytecode, the format that Android runs.
  4. 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.
  5. 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

  1. Question 1 of 2 Does an Android phone run your app's class files on a JVM?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: No; d8 compiles the bytecode into DEX bytecode, which ART runs

    An Android app is compiled to Java bytecode on a computer with a JDK, then d8 turns that bytecode into DEX bytecode, and the phone runs it on ART, the Android runtime.

  2. Question 2 of 2 A team must run a Spring Boot 4.1.1 service next to Apache Kafka on the same machine. What is the oldest Java they can install for both?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Java 17

    Each tool documents its oldest Java: Spring Boot 4.1.1 needs Java 17 or later and so does Kafka. The oldest version that satisfies both is Java 17; any later one works too.

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.

Describe.java: the exercise Java · Describe.java
// 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:

The checks before you start Python · describe_session.py
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:

session.py: runs the commands of a session Python · session.py
"""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.

  1. Question 1 of 17 Which program turns Hello.java into bytecode?

    Choose one answer.

    Show the answer: Question 1 of 17

    Answer: javac, the compiler

    javac compiles source code into class files of bytecode. The java launcher starts a JVM that runs those class files, the JIT compiler turns hot bytecode into machine code while the program runs, and javap only prints what a class file contains.

  2. Question 2 of 17 In the session "Compile, inspect and run", which major version does javap -v report for Hello.class?

    Type a number.

    Show the answer: Question 2 of 17

    Answer: 69

    Class files compiled for Java 25 have major version 69, stored as the bytes 00 45 after the magic number cafe babe (0x45 is 69). Java 21 class files have major version 65.

  3. Question 3 of 17 You compile Hello.java with JDK 25 on a Mac with Apple silicon. Can the class file run unchanged on a Windows PC with an Intel processor and JDK 25?

    Choose one answer.

    Show the answer: Question 3 of 17

    Answer: Yes, because bytecode is written for the JVM, not for a processor or an operating system

    javac compiles to bytecode, not to the processor's instructions, so one class file runs on any operating system and processor that has a JVM of version 25 or later. The JVM there turns the bytecode into its own machine code.

  4. Question 4 of 17 What does the JVM check when linking verifies a class?

    Choose one answer.

    Show the answer: Question 4 of 17

    Answer: That its bytecode is well formed and cannot break the JVM's rules

    Linking verifies the bytecode, checking that it is well formed and cannot break the JVM's rules, and then prepares the class in memory. A class file that fails verification never runs.

  5. Question 5 of 17 A class declares a static initialiser that prints ready, and its main prints hello. In which order do the two lines appear?

    Choose one answer.

    Show the answer: Question 5 of 17

    Answer: ready first, then hello

    Before main runs, the class is loaded, linked and initialised, and initialising runs its static initialisers. So the static initialiser prints ready before main prints hello, on every run.

  6. Question 6 of 17 What does the option -Xint change when you run java -Xint -cp out Busy?

    Choose one answer.

    Show the answer: Question 6 of 17

    Answer: It switches the JIT compiler off, so every bytecode instruction is interpreted

    By default the JVM runs in mixed mode: it interprets bytecode and compiles hot methods to machine code. -Xint keeps only the interpreter, which is why the same loop took several times as long and java -Xint -version reports interpreted mode.

  7. Question 7 of 17 A colleague's java -version ends in (build 25.0.4.1+1-LTS, interpreted mode, sharing). What does that tell you about how their JVM was started?

    Choose one answer.

    Show the answer: Question 7 of 17

    Answer: With the JIT compiler switched off, as the option -Xint does

    The mode in the last line of java -version reports how the JVM executes bytecode: mixed mode by default, interpreted mode when the JIT compiler is switched off with -Xint. Programs then run slower, with the same results.

  8. Question 8 of 17 Temurin 21 refused to run the Hello.class that JDK 25 compiled. Why?

    Choose one answer.

    Show the answer: Question 8 of 17

    Answer: The class file has version 69, and a Java 21 JVM runs class files only up to version 65

    A JVM runs class files of its own version and older ones. The error names both numbers: class file version 69.0, and a runtime that recognises versions up to 65.0. Class files are portable across operating systems, and running a program never changes its class files.

  9. Question 9 of 17 Does a library compiled years ago for Java 8 run on a JDK 25 JVM?

    Choose one answer.

    Show the answer: Question 9 of 17

    Answer: Yes, because a JVM runs class files of its own version and of every earlier version

    The class file version works in one direction: a JVM accepts its own version and every earlier one. That is why old libraries keep working on new JDKs, while new class files fail on old JVMs.

  10. Question 10 of 17 Hello.class was compiled once with JDK 25, yet on Temurin 27 it printed Hello from Java 27. Why not Java 25?

    Choose one answer.

    Show the answer: Question 10 of 17

    Answer: The bytecode asks the JVM that runs it for its version, through Runtime.version()

    The program does not contain the number 25. It calls Runtime.version() while it runs, and the JVM that runs it answers: Temurin 27 says 27. The class file itself, version 69, is unchanged.

  11. Question 11 of 17 What does a JRE leave out that a JDK has?

    Choose one answer.

    Show the answer: Question 11 of 17

    Answer: The compiler and the other development tools

    A JRE holds a JVM and the standard library, for machines that only run Java programs. A JDK adds javac, javap, jshell and the other tools that you need to write Java.

  12. Question 12 of 17 Which of these is a specification rather than software you can install?

    Choose one answer.

    Show the answer: Question 12 of 17

    Answer: Java SE 25

    Java SE is the specification. OpenJDK implements it, vendors such as Eclipse Adoptium build JDKs from OpenJDK, and HotSpot is the JVM inside those builds.

  13. Question 13 of 17 Which of these releases are LTS releases?

    Choose every answer that is right.

    Show the answer: Question 13 of 17

    Answer:

    • JDK 25
    • JDK 11
    • JDK 21

    Oracle's roadmap lists 8, 11, 17, 21 and 25 as LTS releases, one every two years since 17, and plans 29 as the next. The releases in between, such as 24, 26 and 27, stop receiving updates once the next feature release is out.

  14. Question 14 of 17 Temurin 25.0.4.1 has four numbers in its version. What kind of release does the fourth number point to?

    Choose one answer.

    Show the answer: Question 14 of 17

    Answer: An extra update for an urgent security fix, released between the quarterly updates

    Update releases arrive four times a year, and an urgent security fix that cannot wait gets an extra update in between, with a fourth number in its version: Temurin 25.0.4.1 is one of those.

  15. Question 15 of 17 Why does this track teach JDK 25 rather than JDK 27, the newest release?

    Choose one answer.

    Show the answer: Question 15 of 17

    Answer: JDK 25 is an LTS release that receives updates for years, and compact source files became final in it

    Many teams, courses and tools settle on an LTS release because it keeps receiving updates for years, and JDK 25 is also where the short form of Hello.java became a permanent part of Java. Newer features carry a version label.

  16. Question 16 of 17 How does the Java code of an Android app run on the phone?

    Choose one answer.

    Show the answer: Question 16 of 17

    Answer: The build turns its bytecode into DEX bytecode, which ART, the Android runtime, runs

    Android's documentation says the JVM is not used on Android devices. The d8 tool compiles Java bytecode into DEX bytecode, and ART runs it. Apps may be written in Java or Kotlin.

  17. Question 17 of 17 Why does a lesson about a Java 21 language feature carry a note for Android developers?

    Choose one answer.

    Show the answer: Question 17 of 17

    Answer: Android's table of Java versions ends at Java 17, so newer features may not be available in Android builds

    Android builds support Java language features up to Java 17, according to Android's table of Java versions. A feature from Java 21 or later may not work there, so the lessons that teach one say so.

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.

  1. 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.

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. 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.

    Model answer, Pro. First step and follow-ups

Key takeaways

  • javac compiles .java source into .class files of bytecode once, and the JVM runs those class files every time the program runs.
  • Before main runs, 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

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.