Java Module 1 – Start here: JDK 25 LTS and your first programs
Java versions, LTS and preview features
Read a JEP, run a preview feature with --enable-preview, see why previews change between releases, and tell final, preview and incubator features apart.
What you will learn
- Read a JEP page and find its status, release and type
- Run a preview feature with --enable-preview and explain why previews may change
- Use this track's version labels to tell final, preview and incubator features apart
- Compile for an older release with javac --release, and explain why many teams build on an LTS release
Before you start
What you’ll learn · Before you start
What you will learn
- Read a JEP page and find its status, release and type
- Run a preview feature with --enable-preview and explain why previews may change
- Use this track's version labels to tell final, preview and incubator features apart
- Compile for an older release with javac --release, and explain why many teams build on an LTS release
Before you start
On this page
Every Java feature reaches you in one of three states. A final feature is a permanent part of the Java SE platform
and works without any option. A preview feature: A fully specified and implemented feature that is not yet permanent. It needs --enable-preview to compile and to run, its class files carry minor version 65535, and a later release may change or remove it. is fully specified and implemented
but not yet permanent: it is switched off unless you compile and run with --enable-preview, and it may still change
or disappear in the next release. An incubator module: A module whose name starts with jdk.incubator and that holds an API not yet ready for preview. It needs --add-modules, the JVM warns when it is used, and its packages are renamed when it is promoted. feature is an API in a module whose
name starts with jdk.incubator, which the JDK leaves out until you add it with --add-modules, and which is expected
to change. Each change to the JDK is described in a JDK Enhancement Proposal, 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., whose title
and header tell you which state a feature is in and which release carries it. The states matter when you choose a
release: preview code is tied to one release, and tools take time to support each new one, which is why many teams
build on an LTS release such as JDK 21 or JDK 25.
A JEP’s title and header tell you a feature’s state
Every JEP has a page at openjdk.org/jeps/ followed by its number. Its header holds the facts you need, and its
title carries a label while the feature is not final:
- The title suffix, such as
(Preview),(Third Preview)or(Tenth Incubator), says that the feature is not final yet and which round of previewing or incubating this is. A final feature’s JEP has a plain title. - Type (Feature, Infrastructure, Informational or Process) says whether the JEP changes the JDK or describes how OpenJDK works.
- Scope is SE for a change to the Java SE specification, which every compatible JDK has; JDK for a feature of the JDK outside the specification, such as the incubating Vector API; and Implementation for a change inside the JDK’s code alone, such as which garbage collector is the default.
- Status (Candidate, Targeted, Integrated, Closed / Delivered) says how far the JEP has come; Closed / Delivered means it shipped in the release that the Release field names.
- Release is the JDK release that delivered, or will deliver, the JEP, such as 25.
The status follows a fixed path. A JEP is drafted and submitted; as a Candidate it is on the roadmap but promised to no release; its owner then proposes it for one release, and once the plan is accepted for that release it is Targeted; its code then goes into the main code base (Integrated), its tests follow (Complete), and when that release ships it is Closed as Delivered. A JEP can also end as Withdrawn or Rejected. Step through the path, including the way back for a JEP that is dropped from its release:
The drawing shows the whole scene; its 9 steps are listed below.
Every step as text
- Draft. A JEP starts as a Draft, which its owner writes and revises until it is endorsed.
- Submitted. The owner submits it, declaring it ready to be evaluated for the JDK Roadmap.
- Candidate. The OpenJDK Lead adds it to the roadmap as a Candidate, which is when it receives its number. A Candidate is an idea worth considering, promised to no release.
- Proposed to Target. Once a credible engineering plan is written down, the owner proposes the JEP for one specific release.
- Targeted. The Project Lead of that release accepts it once the project's developers broadly agree, and the JEP is Targeted.
- Dropped. A Targeted JEP can still be dropped from its release. If the drop is accepted, it goes back to Candidate and waits for another release.
- Integrated. Its code and unit tests go into the main code base, and the JEP is Integrated.
- Complete. When its functional, performance and conformance tests are delivered, the JEP is Complete, and only bug fixes are expected.
- Closed / Delivered. When the release ships, the JEP is Closed / Delivered, and its Release field names that release. A JEP can also end as Closed / Withdrawn, by its owner, or Closed / Rejected.
The project page of each release, such as openjdk.org/projects/jdk/27/, lists the JEPs it delivers, which is the
quickest way to see what a release contains.
Checkpoint
Check: Reading a JEP
A preview is off by default and tied to one release
JDK 25 previews primitive types in patterns (JEP 507, its third preview), which let a switch on an int use
patterns such as case int c when c >= 500. This program uses them:
// Primitive type patterns in switch: a preview language feature in JDK 25 (JEP 507) and JDK 27 (JEP 532).
public class Status {
static String describe(int code) {
return switch (code) {
case 200 -> "OK";
case int c when c >= 500 -> "server error " + c;
case int c -> "other status " + c;
};
}
public static void main(String[] args) {
System.out.println(describe(200));
System.out.println(describe(503));
System.out.println(describe(404));
}
} The session compiles and runs it with and without previews on JDK 25, then tries the class file on JDK 27:
from session import run
# A preview feature on JDK 25: rejected by default, compiled and run with --enable-preview, and tied to its release.
run("""
javac -d out Status.java
javac --release 25 --enable-preview -d out Status.java
javap -v out/Status.class | grep -E "(minor|major) version"
java -cp out Status
java --enable-preview -cp out Status
javac --release 24 --enable-preview -d out24 Status.java
""", expect_failure=[
"javac -d out Status.java",
"java -cp out Status",
"javac --release 24 --enable-preview -d out24 Status.java",
])
# The same class file on the next releases' JVM, previews switched on.
run("java --enable-preview -cp out Status", jdk="27", expect_failure=["java --enable-preview -cp out Status"]) Output
# JDK in use: openjdk version "25.0.4.1" LTS
$ javac -d out Status.java
Status.java:6: error: primitive patterns are a preview feature and are disabled by default.
case int c when c >= 500 -> "server error " + c;
^
(use --enable-preview to enable primitive patterns)
1 error
[exit status 1]
$ javac --release 25 --enable-preview -d out Status.java
Note: Status.java uses preview features of Java SE 25.
Note: Recompile with -Xlint:preview for details.
$ javap -v out/Status.class | grep -E "(minor|major) version"
minor version: 65535
major version: 69
$ java -cp out Status
Error: LinkageError occurred while loading main class Status
java.lang.UnsupportedClassVersionError: Preview features are not enabled for Status (class file version 69.65535). Try running with '--enable-preview'
[exit status 1]
$ java --enable-preview -cp out Status
OK
server error 503
other status 404
$ javac --release 24 --enable-preview -d out24 Status.java
error: invalid source release 24 with --enable-preview
(preview language features are only supported for release 25)
[exit status 2]
# JDK in use: openjdk version "27"
$ java --enable-preview -cp out Status
Error: LinkageError occurred while loading main class Status
java.lang.UnsupportedClassVersionError: Status (class file version 69.65535) was compiled with preview features that are unsupported. This version of the Java Runtime only recognizes preview features for class file version 71.65535
[exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 preview_session.py
Each step shows one of the rules of JEP 12:
- Off by default. Plain
javacrefuses the program:primitive patterns are a preview feature and are disabled by default. - Opt in when compiling.
javac --release 25 --enable-previewcompiles it and adds two notes saying so. The--enable-previewoption is accepted only together with the current release, so the attempt with--release 24is refused. - The class file is marked.
javapreports minor version 65535 under the usual major version 69: all 16 bits of the minor version are set, which the JVM specification reserves for class files that depend on the preview features of that release. - Opt in again when running.
javawithout the option will not load the class and suggests--enable-preview; with it, the program runs. - Previews never cross releases. JDK 27’s JVM refuses the class even with previews enabled, because it only recognises the preview features of its own release, class file version 71.65535. The source has to be compiled again for JDK 27, and it compiles only if the preview has not changed in between.
Step through the same session from the point of view of the class file:
The drawing shows the whole scene; its 7 steps are listed below.
Every step as text
- Off by default. Plain javac refuses Status.java, because primitive patterns are a preview feature and are disabled by default.
- Opt in to compile. javac --release 25 --enable-preview compiles it, with two notes saying so. The option is accepted only together with the current release, so --release 24 is refused.
- The class file is marked. javap reports minor version 65535 under the usual major version 69. All 16 bits of the minor version are set, which marks a class file that depends on the preview features of JDK 25.
- Run without the option. Without --enable-preview, the JDK 25 JVM will not load the class, and its error suggests running with --enable-preview.
- Opt in to run. With --enable-preview the class runs and prints OK, server error 503 and other status 404.
- The next release. The JVM of JDK 27 refuses the class even with previews enabled, because it recognises only the preview features of its own release, class file version 71.65535.
- Compile again. So the source has to be compiled again for JDK 27, and it compiles only if the preview has not changed in between.
That last rule is the reason for a warning in JEP 12: class files that rely on preview features are for the developer who opted in, and are not meant to be shipped to anyone else’s machines.
Hex Viewer & File Inspector Open out/Status.class: the bytes after CA FE BA BE are FF FF, the minor version 65535 of a preview class file.Checkpoint
Check: The rules for preview features
Previews really do change between releases
A feature usually needs several JEPs, one per round. The diagram follows two of them:
Two features on their way through previews
Text description of the diagram
The diagram shows two features moving through preview releases, each from top to bottom.
Compact source files: a first preview in JDK 21 (JEP 445), where they were called unnamed classes; a second preview in JDK 22 (JEP 463); a third in JDK 23 (JEP 477); a fourth in JDK 24 (JEP 495), where they were called simple source files; and final in JDK 25 (JEP 512) as compact source files.
Lazy constants: a first preview in JDK 25 (JEP 502), under the name stable values; a second preview in JDK 26 (JEP 526), where the API was renamed lazy constants; and a third preview in JDK 27 (JEP 531). Whether the feature becomes final, changes again or is removed is decided in a later release.
Compact source files, the subject of lesson 3, went through four previews under three different names before JEP 512 made them final in JDK 25. Stable values, previewed in JDK 25, were renamed lazy constants in their second preview in JDK 26 and are in their third preview in JDK 27. JEP 12, the rules for previews, says that two rounds of previewing are the norm, and that a preview ends either as a permanent feature, with or without changes, or by being removed.
A preview API can be renamed or reshaped from one release to the next. This file uses the stable values preview of JDK 25:
// A value computed once, on first use, with the StableValue preview API of JDK 25 (JEP 502).
final StableValue<String> greeting = StableValue.of();
void main() {
IO.println(greeting.orElseSet(() -> "computed once"));
IO.println(greeting.orElseSet(() -> "never used"));
} // The same idea with the LazyConstant preview API that replaced StableValue (JEP 526 in JDK 26, JEP 531 in JDK 27).
final LazyConstant<String> greeting = LazyConstant.of(() -> "computed once");
void main() {
IO.println(greeting.get());
IO.println(greeting.get());
} from session import run
# A preview API on JDK 25, the same file on JDK 27, and the renamed API on JDK 27.
run("java --enable-preview Settings.java")
run("""
java --enable-preview Settings.java
java --enable-preview Lazy.java
""", jdk="27", expect_failure=["java --enable-preview Settings.java"]) Output
# JDK in use: openjdk version "25.0.4.1" LTS
$ java --enable-preview Settings.java
computed once
computed once
# JDK in use: openjdk version "27"
$ java --enable-preview Settings.java
Settings.java:2: error: cannot find symbol
final StableValue<String> greeting = StableValue.of();
^
symbol: class StableValue
location: class Settings
Settings.java:2: error: cannot find symbol
final StableValue<String> greeting = StableValue.of();
^
symbol: variable StableValue
location: class Settings
2 errors
error: compilation failed
[exit status 1]
$ java --enable-preview Lazy.java
computed once
computed once
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 churn_session.py
On JDK 25, with previews enabled, Settings.java computes its value once and prints it twice. On JDK 27 the same file
no longer compiles: cannot find symbol for StableValue, because JEP 526 renamed the API to LazyConstant and
removed low-level methods such as orElseSet. Lazy.java, written for the new API, runs on JDK 27. Code that relied
on the preview had to be rewritten, which is exactly the risk a preview carries.
Key idea
A preview can be renamed, reshaped or removed in the next release, so code that uses one may have to be rewritten,
as StableValue became LazyConstant between JDK 25 and JDK 26.
Checkpoint
Check: Previews that change
An incubator module stays out until you add it
An incubator module holds an API that is not ready for the preview process yet. The Vector API, which lets a program
work on several numbers in one processor instruction, has incubated in the module jdk.incubator.vector since JDK 16;
JDK 25 carries its tenth round and JDK 27 its twelfth. Its JEP says it will stay there until features of Project
Valhalla that it needs, such as value objects, become available as previews; value objects are targeted to JDK 28 as a
preview.
// The Vector API is an incubating API in the module jdk.incubator.vector.
import jdk.incubator.vector.IntVector;
import jdk.incubator.vector.VectorSpecies;
void main() {
VectorSpecies<Integer> species = IntVector.SPECIES_128;
IO.println("int lanes in a 128-bit vector: " + species.length());
IntVector a = IntVector.fromArray(species, new int[] {1, 2, 3, 4}, 0);
IntVector b = IntVector.fromArray(species, new int[] {10, 20, 30, 40}, 0);
IO.println("lane-wise sum: " + a.add(b));
} from session import run
# An incubator module is not resolved unless you ask for it with --add-modules.
run("""
java Lanes.java
java --add-modules jdk.incubator.vector Lanes.java
""", expect_failure=["java Lanes.java"]) Output
# JDK in use: openjdk version "25.0.4.1" LTS
$ java Lanes.java
Lanes.java:2: error: package jdk.incubator.vector is not visible
import jdk.incubator.vector.IntVector;
^
(package jdk.incubator.vector is declared in module jdk.incubator.vector, which is not in the module graph)
Lanes.java:3: error: package jdk.incubator.vector is not visible
import jdk.incubator.vector.VectorSpecies;
^
(package jdk.incubator.vector is declared in module jdk.incubator.vector, which is not in the module graph)
2 errors
error: compilation failed
[exit status 1]
$ java --add-modules jdk.incubator.vector Lanes.java
WARNING: Using incubator modules: jdk.incubator.vector
int lanes in a 128-bit vector: 4
lane-wise sum: [11, 22, 33, 44]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 incubator_session.py
Without --add-modules jdk.incubator.vector the compiler cannot see the package at all, because incubator modules are
left out of the default set of modules. With the option the program runs, and the JVM prints
WARNING: Using incubator modules first: JEP 11 requires a warning whenever an incubator module is used. When an
incubating API is finally promoted, its packages are renamed, so even the import lines of code like this will change.
Checkpoint
Check: Incubator modules
Final, preview and incubator features ask different things of your code
The three states side by side:
- Final features are always on and change only through deprecation and removal over several releases; their class files are ordinary. Compact source files (JEP 512) are an example in JDK 25. Use them for all code you ship.
- Preview features are switched on with
--enable-previewwhen compiling and when running, and may change or be removed until a later JEP makes them final; their class files carry minor version 65535 and load only on the same feature release. Primitive types in patterns (JEP 507) and stable values (JEP 502) are examples in JDK 25. Use them for experiments and for feedback on the release that has them. - Incubator features are switched on with
--add-modulesfor their module, and their packages are renamed when they are promoted; their class files are ordinary, but the JVM warns when the module is used. The Vector API (JEP 508) is the example in JDK 25. Use it for experiments, with code you expect to rewrite.
Whether your code may use a state depends on where the code goes. Answer two questions about it in the table:
Answer the questions above: the table then marks what fits your case and says why the rest does not.
| State | Switched on with | Class files | May still change |
|---|---|---|---|
| Final Example in JDK 25: compact source files (JEP 512) | Good nothing: always on | Good ordinary, and they run on later releases | Good only through deprecation and removal over several releases |
| Preview Example in JDK 25: primitive types in patterns (JEP 507) | Mixed --enable-preview, when compiling and when running | Poor minor version 65535; they load only on the same feature release | Poor yes, or be removed, until a later JEP makes it final |
| Incubator Example in JDK 25: the Vector API (JEP 508) | Mixed --add-modules for its module | Mixed ordinary, but the JVM warns when the module is used | Poor yes, and its packages are renamed when it is promoted |
How the answers decide
- “Will the code be shipped to other people's machines?” Yes, it ships: rules out Preview. JEP 12 says that class files which rely on preview features are for the developer who opted in, not for other people's machines.
- “Will the code be shipped to other people's machines?” Yes, it ships: adds a caveat to Incubator. An incubating API is expected to change, and its packages are renamed when it is promoted, so shipped code will need rewriting.
- “Must the code keep compiling and running, unchanged, on the next LTS release?” Yes: rules out Preview. Preview class files load only on their own feature release, and the source compiles again only if the preview has not changed.
- “Must the code keep compiling and running, unchanged, on the next LTS release?” Yes: adds a caveat to Incubator. The Vector API has incubated since JDK 16 and is expected to change, so the next LTS may need new code or new imports.
- “Will the code be shipped to other people's machines?” No, it is an experiment: For an experiment every state works, as long as you pass --enable-preview or --add-modules on the release that has the feature.
In short: shipped code and code that must survive the next LTS use final features only, while an experiment may use any of the three on the release that has it. This track marks each state in its lessons:
How this track labels versions
A lesson without a label uses only what is final in JDK 25 LTS. JDK 26+ or JDK 27+ marks something that is
final only from that release on and does not compile on JDK 25. Preview in 25 or Preview in 27 marks a preview
feature: the example needs --enable-preview on exactly that release, and the feature may change. Incubator marks
an incubating API that needs --add-modules. Targeted to JDK 28 (not released) marks a JEP for a release that
has not shipped, which you can only read about or try in early-access builds.
Checkpoint
Check: The three states and their labels
Many teams build on an LTS release, and javac compiles for older ones
Three facts from this lesson and lesson 1 explain the habit:
- Updates last longer. A feature release receives updates for six months; an LTS release for years. Adoptium lists Temurin 25 until at least 2031.
- Tools need time. JaCoCo 0.8.15, a code-coverage tool for Java, supports Java 26 officially but reads Java 27 class files only experimentally, and Spring Boot 4.1.1 is documented as compatible with Java up to 26. Right after a feature release, some of your tools may not support it yet.
- Previews stay behind. Code that depends on a preview is tied to one feature release and has to be recompiled, and often rewritten, for the next one.
When code must run on an older release than your JDK, compile it with javac’s
--release option: The javac option that compiles for an older Java release: by that release's language rules, against its API and into class files of its version, so javac --release 21 writes version 65., --release. The javac documentation says the option compiles
according to the rules of the language for that release, against that release’s API, and writes class files that
target it:
// Uses List.reversed(), a method that arrived in JDK 21 with sequenced collections.
import java.util.List;
public class Recent {
public static void main(String[] args) {
List<String> releases = List.of("21", "25", "27");
System.out.println("Newest first: " + releases.reversed());
}
} from session import run
# javac --release N compiles against the language and the API of release N, and writes class files for it.
run("""
javac --release 21 -d out21 Recent.java
javap -v out21/Recent.class | grep "major version"
javac --release 17 -d out17 Recent.java
""", expect_failure=["javac --release 17 -d out17 Recent.java"])
run("java -cp out21 Recent", jdk="21") Output
# JDK in use: openjdk version "25.0.4.1" LTS
$ javac --release 21 -d out21 Recent.java
$ javap -v out21/Recent.class | grep "major version"
major version: 65
$ javac --release 17 -d out17 Recent.java
Recent.java:7: error: cannot find symbol
System.out.println("Newest first: " + releases.reversed());
^
symbol: method reversed()
location: variable releases of type List<String>
1 error
[exit status 1]
# JDK in use: openjdk version "21.0.12.1" LTS
$ java -cp out21 Recent
Newest first: [27, 25, 21]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 release_flag_session.py
With --release 21, JDK 25’s compiler wrote a class file of version 65, which JDK 21 ran. With --release 17 it
refused the program, because List.reversed() does not exist in the Java 17 API: the release option checks the
library you call as well as the class file version.
Key idea
An LTS release keeps receiving updates for years, and javac --release N builds class files for release N, checked
against that release’s language rules and API.
Checkpoint
Check: LTS releases and javac --release
Practise: classify ten features
For each feature below, open its JEP page (openjdk.org/jeps/ and the number) and decide its state in the JDK 25 that
this track uses: final in JDK 25, final only in a later release, a preview, or an incubator. The title suffix and the
Release field are all you need, and each answer explains what the page says.
Checkpoint
Features 1 to 3
Checkpoint
Features 4 to 6
Checkpoint
Features 7 and 8
Checkpoint
Features 9 and 10
With the ten features classified, practise the six ideas of the lesson in a short session. It begins where your answers so far were weakest, and every answer is explained before the next question:
Practice that adapts to you
Practise this lesson
13 questions about 6 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.
Interview questions
Fresher · What is the difference between a preview feature and an incubator module in Java?
A preview feature is a language, JVM or API feature that is fully specified and implemented but not yet permanent.
It is off unless you compile with --enable-preview and the current --release, and run with --enable-preview;
class files that use it are marked with minor version 65535 and run only on that same feature release. An incubator
module holds a non-final API in a module whose name starts with jdk.incubator, such as jdk.incubator.vector; you
add it with --add-modules, and the JDK prints a warning when it is used. Both exist to gather feedback before a
feature becomes final. A preview usually becomes final after two or more rounds, or is removed; an incubating API
moves to a preview or to a final module, and its packages are renamed on the way.
Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.
-
Mid to senior
A teammate wants to ship a service compiled with --enable-preview on JDK 25, because a preview API makes one part of the code much shorter. What risks do you raise, with evidence, and what would you suggest instead?
-
Senior to staff
Your services run on Java 17. Management asks whether to move to Java 21 or straight to Java 25, and what it will take. How do you decide, and what do you check in the build, the tools and the dependencies before the first service moves?
Key takeaways
- A JEP’s title suffix and its Release field tell you whether a feature is final, a preview or an incubator, and in which JDK, and its status follows a fixed path from Draft to Closed / Delivered.
- Preview features need
--enable-previewat compile time (with the current--release) and at run time, and their class files carry minor version 65535 and load only on the same feature release. - Previews can change completely between releases:
StableValuein JDK 25 becameLazyConstantin JDK 26. - Incubator modules need
--add-modules, print a warning, and get new package names when promoted, so shipped code uses final features only. - Teams build on an LTS because updates last years, tools take time to support new releases, and previews stay with
their release, and
javac --release Nbuilds for an older release and checks its API too.
Terms in this lesson
- --release option
- The javac option that compiles for an older Java release: by that release's language rules, against its API and into class files of its version, so javac --release 21 writes version 65.
- incubator module
- A module whose name starts with jdk.incubator and that holds an API not yet ready for preview. It needs --add-modules, the JVM warns when it is used, and its packages are renamed when it is promoted.
- 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.
- preview feature
- A fully specified and implemented feature that is not yet permanent. It needs --enable-preview to compile and to run, its class files carry minor version 65535, and a later release may change or remove it.
References
- JEP 12: Preview Features (OpenJDK)
- JEP 11: Incubator Modules (OpenJDK)
- JEP 2.0, draft 2 (the states of a JEP) (OpenJDK)
- JEP 0: JEP Index (OpenJDK)
- JEP 507: Primitive Types in Patterns, instanceof, and switch (Third Preview) (OpenJDK)
- JEP 502: Stable Values (Preview) (OpenJDK)
- JEP 526: Lazy Constants (Second Preview) (OpenJDK)
- JEP 531: Lazy Constants (Third Preview) (OpenJDK)
- JEP 532: Primitive Types in Patterns, instanceof, and switch (Fifth Preview) (OpenJDK)
- JEP 543: Structured Concurrency (OpenJDK)
- JEP 508: Vector API (Tenth Incubator) (OpenJDK)
- JEP 523: Make G1 the Default Garbage Collector in All Environments (OpenJDK)
- JEP 512: Compact Source Files and Instance Main Methods (OpenJDK)
- JDK 25 (OpenJDK)
- JDK 26 (OpenJDK)
- JDK 27 (OpenJDK)
- JDK 28 (OpenJDK)
- The Java Virtual Machine Specification, Java SE 25: 4.1, The ClassFile Structure (Oracle)
- Preview Language and VM Features (Java Language Updates, JDK 25) (Oracle)
- The javac Command (JDK 25 tool reference, --release) (Oracle)
- JaCoCo Change History (JaCoCo (Mountainminds))
- Spring Boot System Requirements (Spring)
- Temurin Support and Release Roadmap (Eclipse Adoptium)
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress