What Java is

Java is a general-purpose programming language and the platform it runs on. It is one of the most used languages in business software: web back ends, banking and insurance systems, energy and telecom platforms, middleware, monitoring tools and many of the portals that service desk and operations people work with every day. A few properties shape how it feels:

  • Statically typed. Every variable has a type that is fixed in the code, and the compiler checks every use of it before the program runs. See static and dynamic typing.
  • Object-oriented. Code is organized in classes and other types (see Object-Oriented Concepts); since Java 8 (2014) functions can also be passed around as values, in lambdas and streams.
  • Managed. A garbage collector frees memory you no longer use, so you never release memory by hand (see garbage collection).
  • Portable. A compiled Java program runs unchanged on Windows, Linux and macOS, on Intel and Arm processors: the compiler produces instructions for a virtual machine, not for a particular processor.

Here is a complete Java program. It works out the average of some daily meter readings:

// Daily electricity use (kWh) of one Kestrel Energy household
void main() {
    double[] readings = {11.2, 9.8, 12.5, 10.1, 13.4};

    double total = 0;
    for (double kwh : readings) {
        total = total + kwh;
    }

    double average = total / readings.length;
    IO.println("Days measured: " + readings.length);
    IO.println("Average per day: " + String.format("%.1f", average) + " kWh");
}
Days measured: 5
Average per day: 11.4 kWh

Blocks are marked with curly braces { }, statements end with a semicolon, // starts a comment, and IO.println prints a line. Each variable is declared with its type: double is a floating-point number and double[] an array of them. The program starts in the method main. This short form, a file with just a void main(), is new in Java 25; most existing code uses the longer classic form with public static void main(String[] args) inside a class. The next page, The JDK, javac, java and Your First Program, explains both and shows how to run a file like this.

Because the types are known in advance, the compiler catches a whole class of mistakes before anyone runs the program. Assigning text to a number is one of them; this program never starts:

void main() {
    int customersAffected = "1250";
    IO.println(customersAffected);
}
Main.java:2: error: incompatible types: String cannot be converted to int

The message names the file and line (Main.java:2) and describes the problem; below it, the compiler prints the line with a caret ^ under the spot. In Python or JavaScript the same mistake would only show up when that line runs, and perhaps not at all.

A short history

Java started at Sun Microsystems in the early 1990s, in a project led by James Gosling; its first name was Oak. Sun formally introduced Java in May 1995 and released JDK 1.0 in early 1996. The slogan was "write once, run anywhere": one compiled program for every kind of computer, at a time when software usually had to be rebuilt for each operating system. Oracle bought Sun in 2010 and has led Java's development since, in the open-source OpenJDK project.

Version Released What it brought (selection)
Java 5 2004 Generics, the enhanced for loop, autoboxing, enums, annotations
Java 8 (LTS) Mar 2014 Lambdas, streams, java.time, Optional, default methods
Java 9 2017 The module system, JShell
Java 11 (LTS) Sep 2018 Run a single source file directly; no more separate JRE from Oracle
Java 17 (LTS) Sep 2021 Records, text blocks, sealed classes, switch expressions
Java 21 (LTS) Sep 2023 Virtual threads, pattern matching for switch, record patterns, sequenced collections
Java 25 (LTS) Sep 2025 Compact source files with void main(), the IO class, module imports, flexible constructor bodies, scoped values

Features usually arrive first as a preview in one or more releases, switched off unless you ask for them, and become final later. The column above names the release where a feature became final (records, for example, were final in Java 16 and are listed under the first LTS release that had them).

How Java code runs

Running a Java program takes two translation steps, one before the program runs and one while it runs.

  1. The Java compiler, javac, reads your .java files, checks the types and translates every class into a .class file containing Java bytecode: compact instructions for an imaginary processor, the same on every operating system. The class file also describes the class's fields and methods.
  2. The Java Virtual Machine (JVM) loads the class files and runs the bytecode. It starts by interpreting it, instruction by instruction, while measuring which methods run often. Its just-in-time (JIT) compiler then translates those hot methods into machine code for the actual processor. The JVM also manages memory with its garbage collector, checks types and array bounds at run time, and turns errors into exceptions.
From source code to machine code. At build time, the Java compiler javac turns the source file Meter.java into Java bytecode, stored in the class file Meter.class. At run time, the Java Virtual Machine loads the class file; its interpreter runs the bytecode, and its JIT compiler turns frequently used methods into machine code for the actual processor. The garbage collector manages memory. Build time Run time Source code Meter.java Java compiler javac Java bytecode Meter.class JVM loads classes Interpreter JIT compiler garbage collector Machine code
The compiler runs once, when you build; the JVM interprets the bytecode and compiles the busiest methods to machine code while the program runs.

This design is close to that of C# and .NET (Intermediate Language plus a runtime with a JIT compiler; see How C# code runs) and different from Python's, where an interpreter reads your source code each time you run it. It has three practical effects:

  • The same .class files, usually packed in a .jar archive, run on any machine with a suitable JVM. A Java application is delivered once, not once per platform.
  • A Java program starts more slowly than a fully compiled one and gets faster after it has run for a while ("warm-up"), because the JIT compiler optimizes what it sees being used. Long-running servers profit most.
  • A class file records which Java version compiled it. A JVM refuses class files from a newer compiler than itself, with an UnsupportedClassVersionError, so the runtime must be at least as new as the version the application was built for.

The JDK includes javap, which shows the bytecode in a class file. For a tiny class Hello that prints one line, the main method compiles to four instructions:

javac Hello.java
javap -c Hello
  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #7    // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #13   // String Hello from Kestrel Energy!
       5: invokevirtual #15   // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return

You never need to read bytecode to write Java, but it shows what the JVM actually executes: fetch System.out, load a string, call println, return. Many other languages compile to the same bytecode and run on the same JVM, among them Kotlin, Scala, Groovy and Clojure.

The JDK and the JRE

Java SE (Standard Edition) is the specification: the language, the JVM and the standard class library, as defined by the Java Community Process. Concrete software that implements it comes in two packages:

  • The Java Development Kit (JDK) is what you install to write Java. It contains the JVM, the class library, the compiler javac, the launcher java and tools such as jshell, jar, javadoc, jcmd and jlink.
  • The Java Runtime Environment (JRE) is the part needed only to run programs: the JVM and the class library, without the development tools.
The JDK contains the JRE, which contains the JVM. The JVM runs bytecode with its interpreter, JIT compiler and garbage collector. The JRE adds the Java class library. The JDK adds the development tools such as javac, jshell, jar and jcmd. JDK — Java Development Kit javac · java · jshell · jar · javadoc · jcmd · jlink JRE — Java Runtime Environment class library: java.lang · java.util · java.time · java.net … JVM — Java Virtual Machine interpreter · JIT compiler · garbage collector
Each box contains the one inside it: a JDK can do everything a JRE can, plus building programs.

Until Java 8, end users installed a separate JRE from java.com, and browsers could run Java applets with a plug-in. Oracle stopped shipping a separate JRE and that "deployment stack" with Java 11. Today an application either ships its own trimmed runtime, built with the JDK tools jlink or jpackage, or runs on a JDK or JRE that the administrator installs from one of the builds described below; some of them, such as Eclipse Temurin, still offer a JRE download. The Applet API itself was removed in Java 26.

OpenJDK and its builds

OpenJDK is the open-source project in which Java itself is developed, by Oracle together with companies such as Red Hat, SAP, Amazon and Microsoft. Its code is licensed under the GNU General Public License version 2 with the Classpath Exception; the exception means your own programs do not fall under the GPL just because they run on Java.

OpenJDK publishes source code, not the installers most people use. An OpenJDK distribution is a JDK built from that source code by a vendor, tested, and patched on a schedule the vendor promises. They are functionally the same Java; they differ in support periods, platforms, packaging and license terms. The common ones:

Build From Cost
Eclipse Temurin Eclipse Adoptium (vendor-neutral working group) Free
Amazon Corretto Amazon Free
Microsoft Build of OpenJDK Microsoft Free
Red Hat build of OpenJDK, Azul Zulu, BellSoft Liberica, SapMachine Red Hat, Azul, BellSoft, SAP Free downloads; paid support offered
Oracle OpenJDK (jdk.java.net) Oracle Free, but updated for six months per version only
Oracle JDK Oracle Depends on version and date; see below

Linux distributions also package OpenJDK themselves (Debian 12, for example, offers Java 17). Every example on these pages is checked with Eclipse Temurin 25.

Oracle JDK licensing

Oracle's own build has changed license terms several times, which is why companies are careful with it. The situation as of October 2026:

  • Oracle JDK 21 and later are offered under the Oracle No-Fee Terms and Conditions (NFTC): free for everyone, including commercial and production use — but only until one year after the next LTS release.
  • For Oracle JDK 21 that moment has come: updates released from the October 2026 Critical Patch Update (CPU), due on 20 October 2026, are planned to be offered under the Oracle Technology Network (OTN) license instead, which allows personal and development use but not free production use. Oracle JDK 17 updates moved to the OTN license in October 2024, and Java 8 and 11 updates are OTN-licensed as well.
  • Oracle JDK 25 stays under the NFTC until September 2028, one year after Java 29.
  • Production use outside the NFTC needs the paid Java SE Universal Subscription. It is priced per employee of the whole organization (contractors included), not per server; Oracle's price list of 1 March 2023 starts at $15 per employee per month for small organizations.

The practical consequence: an organization running Oracle JDK 21 in production either moves to Oracle JDK 25, takes a subscription, or switches to a free OpenJDK build of the same version. Because the builds are functionally the same Java, that last switch normally needs no code changes, only a new runtime and a test run.

Releases and long-term support

Since Java 10 (2018) a new feature release appears every six months, in March and September, numbered by release: 25, 26, 27. Each vendor then publishes security and bug-fix updates every quarter, in January, April, July and October; they show up in the third number (25.0.4), and an extra update between the regular ones gets a fourth (25.0.4.1).

An LTS release (long-term support) is a feature release that vendors keep patching for years instead of months. Since Java 17, every fourth release is LTS: a new one every two years. The releases between them are supported only until the next one appears, six months later. Production systems almost always run an LTS version.

Version Type Released Free updates until (at least)
Java 29 LTS Planned Sep 2027 —
Java 28 Feature Planned Mar 2027 —
Java 27 Feature 15 Sep 2026 Mar 2027 (Temurin)
Java 26 Feature 17 Mar 2026 Ended Sep 2026
Java 25 LTS 16 Sep 2025 Sep 2031 (Temurin), Oct 2032 (Corretto), Sep 2030 (Microsoft)
Java 21 LTS Sep 2023 Dec 2029 (Temurin), Oct 2030 (Corretto), Sep 2028 (Microsoft)
Java 17 LTS Sep 2021 Oct 2027 (Temurin), Oct 2029 (Corretto), Sep 2027 (Microsoft)

The table shows the vendors' published dates as of October 2026. Java 8 and 11 also still receive updates from several vendors (for Java 8 until at least December 2030 at Temurin and Corretto), which says a lot about how long Java applications live. Oracle sells paid support for its LTS versions on its own schedule, for example Java 25 Premier Support until September 2030.

A small program can check which version it is running on, and do the date arithmetic for a planning note:

void main() {
    IO.println(Runtime.version().feature());
    IO.println(System.getProperty("java.specification.version"));
}
25
25
void main() {
    LocalDate today = LocalDate.of(2026, 10, 5);
    LocalDate nextCpu = LocalDate.of(2026, 10, 20);       // Critical Patch Update
    LocalDate temurin25End = LocalDate.of(2031, 9, 30);   // "at least" Sep 2031

    IO.println("Days until the October 2026 CPU: "
            + ChronoUnit.DAYS.between(today, nextCpu));
    IO.println("Years of Temurin 25 support left: "
            + ChronoUnit.YEARS.between(today, temurin25End));
}
Days until the October 2026 CPU: 15
Years of Temurin 25 support left: 4

The first program prints 25 because these pages are checked on Java 25; on Java 27 it would print 27. LocalDate and ChronoUnit come from the java.time package, covered in Files, I/O and JSON.

The class library

Every JDK comes with a large standard library: thousands of ready-made classes for text, numbers, dates, collections, files, networking, security and concurrency. Classes are grouped in packages with dotted names such as java.util, java.time and java.math, and since Java 9 packages are grouped in modules; the core ones are in the module java.base. An import line at the top of a file lets you write the short class name instead of the full one (LocalDate instead of java.time.LocalDate):

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.time.LocalDate;
import java.util.List;
import java.util.Locale;

// Numbers, text, dates and locales: all from the Java class library
void main() {
    BigDecimal monthlyCost = new BigDecimal("87.456");
    IO.println(monthlyCost.setScale(2, RoundingMode.HALF_UP));

    List<String> regions = List.of("North", "East", "South");
    IO.println(String.join(" | ", regions));

    LocalDate readingDay = LocalDate.of(2026, 10, 3);
    IO.println(readingDay.getDayOfWeek());

    Locale dutch = Locale.forLanguageTag("nl-NL");
    IO.println(NumberFormat.getCurrencyInstance(dutch).format(monthlyCost));
}
87.46
North | East | South
SATURDAY
€ 87,46

In this short file form the whole java.base module is imported automatically, so the import lines are optional here (the two previous examples used LocalDate without one); in a classic class file they are required. Note the Dutch currency format: the euro sign, a non-breaking space, and a decimal comma. Formatting is covered in Strings and Text.

Beyond the JDK, hundreds of thousands of open-source libraries are published on Maven Central, the main repository for Java libraries; build tools such as Maven and Gradle download them for you (see Packages, Modules and Build Tools). Those libraries are part of your application's security, as Log4Shell showed in 2021: a critical flaw in the popular logging library Log4j 2 (CVE-2021-44228, CVSS score 10.0) put a huge number of Java systems at risk even though the JDK itself was fine. Patching Java means patching the libraries too; see Running Java in Production.

Where Java is used

  • Back-end services and web applications, often with the Spring framework (Spring Boot) or on application servers such as Apache Tomcat that implement the Jakarta EE standards (the successor of Java EE). See REST APIs.
  • Enterprise systems in banking, insurance, government, telecom and energy: billing, customer portals, trading and integration platforms that have run for decades.
  • Infrastructure and data tools: many widely used systems, such as Apache Kafka, Elasticsearch and Jenkins, are written in Java or other JVM languages, so operations teams run JVMs even if nobody writes Java.
  • Android apps are written in Kotlin or Java, though Android runs them on its own runtime rather than on a standard JVM.
  • Desktop tools such as the IntelliJ IDEA and Eclipse development environments.

In the Stack Overflow Developer Survey 2025, 29.4% of all respondents said they had used Java. The TIOBE Index of September 2026, which measures search-engine popularity, put Java fourth, after Python, C and C++. Java code at work typically looks like this: a small type that describes an outage ticket, and a list of tickets processed with a stream. Records are explained in Records, Enums and Sealed Types, streams in Lambdas, Functional Interfaces and Streams.

void main() {
    List<Ticket> tickets = List.of(
            new Ticket("INC-20417", "North", 1250),
            new Ticket("INC-20418", "East", 85),
            new Ticket("INC-20421", "North", 430));

    int affected = tickets.stream()
            .filter(t -> t.region().equals("North"))
            .mapToInt(Ticket::customers)
            .sum();

    IO.println(tickets.get(0));
    IO.println("Customers affected in North: " + affected);
}

record Ticket(String id, String region, int customers) {}
Ticket[id=INC-20417, region=North, customers=1250]
Customers affected in North: 1680

Compile-time and run-time errors

The compiler can only check what it knows while building. It knows that "1250" is a string, so assigning it to an int is refused, as shown at the top of this page. It cannot know what a user will type or what a file will contain. Converting text to a number therefore compiles fine and fails only when the program runs with bad input; the JVM then throws an exception:

void main() {
    String fromMeterFile = "12.5 kWh";   // read at run time
    IO.println("Parsing the reading...");
    double reading = Double.parseDouble(fromMeterFile);
    IO.println(reading);
}
Parsing the reading...
Exception in thread "main" java.lang.NumberFormatException: For input string: "12.5 kWh"

"Exception in thread "main"" means nothing caught the error, so the program stopped. The JVM then prints a stack trace: lines starting with at that show which methods were running, ending with at Main.main(Main.java:4), the line in your own code. Operations people see these traces in application logs every day. Static typing removes many errors, not all of them; Exceptions and Error Handling shows how to handle the rest.