Topic 3 of 119 1. Introduction to Java Interactive Tutorial

The Story of Java: From 1991 to Today

19 mins read Last updated: 22 Aug 2026 15,519 views

Direct Answer & Core Concept

Java began at Sun Microsystems in 1991 as a project called Oak, led by James Gosling with Mike Sheridan and Patrick Naughton, and aimed at consumer electronics such as set-top boxes. That market did not materialise, and the project survived by pivoting to the World Wide Web, with Java 1.0 released on 1996-01-23. The following years built the enterprise era, and Java 5 in 2004 is usually treated as the release that made Java a modern language through generics, enums, and autoboxing. Oracle completed its acquisition of Sun in January 2010, after which the platform moved to a predictable six-month feature release cadence starting with JDK 9 in September 2017, alongside a long-term support release roughly every two years. The current LTS is **Java 25** (released 2025-09-16) and the current feature release is **Java 27** (2026-09-15), so Java 8, 11, and 17 all reach end of support during 2027. One common summary is inaccurate: Structured Concurrency is **not** a finished Java 21 feature. It first appeared as an incubating API in Java 19 and has been re-previewed repeatedly, reaching its **seventh preview in Java 27**, whereas virtual threads from Java 21 are genuinely final. The most durable fact in the whole history is backward compatibility, since old bytecode keeps running on new JVMs, which is what allows a system measured in decades to be upgraded in JDK steps rather than rewritten.

Detailed Explanation & Mechanics

1. The Origin: The Green Project and Oak

Java began at Sun Microsystems in **1991** as a project called **Oak**, led by **James Gosling** with Mike Sheridan and Patrick Naughton. The stated goal was software for consumer electronics, specifically set-top boxes for interactive television, plus handheld remotes and other embedded appliances.

The problem it was meant to solve was real. These devices shipped with different processors, and the industry assumption was that software would migrate between them. Writing in C or C++ meant recompiling for each target, and for anything touching the operating system, rewriting the platform-specific code.

Architecture Diagram
THE PROBLEM AS IT LOOKED IN 1991
   ┌───────────────────────────────┬───────────────────────────────┐
   │ Devices used different CPUs    │ Native binaries do not travel │
   ├───────────────────────────────┼───────────────────────────────┤
   │ Set-top boxes, remotes,       │ Recompile for every target,   │
   │ printers, anything embedded   │ and rewrite the OS-specific   │
   │                               │ parts entirely                │
   └───────────────────────────────┴───────────────────────────────┘

The solution was to put a virtual machine between the source and the hardware, so that the platform-specific layer is written once per device rather than once per application.

2. Oak Fails as an Appliance Language, Then Succeeds on the Web

The consumer electronics market did not materialise as expected, and the original business case for Oak largely collapsed. What saved the project was a different distribution channel: the World Wide Web.

Java's first release was **Java 1.0 on 1996-01-23**, and it shipped with class file version **45.0**. The name had already been changed from Oak to Java by this point, in 1995.

The reason the Web turned out to be the perfect host for the language is the same reason the project had been designed for embedded devices: the Web spans heterogeneous hardware, and Java's portability meant a program could run on whatever machine the visitor happened to have.

The early story is usually told as applets in browsers, and it is worth being precise about what that did and did not achieve. Applets did drive enormous public and developer interest, but the durable enterprise adoption of Java came later, through servers. Applets themselves are gone from the platform: java.applet.Applet was deprecated for removal in Java 17 and the Applet API was finally removed in Java 26.

3. The Java 2 and Enterprise Era, 1998 to 2004

**Java 1.2 arrived on 1998-12-04** with codename *Playground* and class file version **46.0**, and it is the release usually treated as the real beginning of Java as a mainstream language. It added the Collections Framework, Swing, strictfp, and the Sun JIT compiler.

The big institutional story of this era is enterprise Java. J2EE, later renamed Java EE, packaged the platform for server-side development, and the Servlet, JDBC, and RMI APIs became the backbone of a large amount of business software. This is when Java became primarily an enterprise language, and it is the origin of much of the ecosystem still in use today.

VersionRelease dateClass fileNotable
Java 1.01996-01-2345.0First official release
Java 1.11997-02-1845.3JDBC, RMI, reflection, JavaBeans
Java 1.21998-12-0446.0Collections, Swing, strictfp
Java 52004-09-3049.0Generics, enums, autoboxing

Between 1.2 and 5 the releases were named after animals and birds, such as *Kestrel* and *Tiger*, which is usually remembered with affection and sometimes with relief.

4. Java 5: The Release That Made Java Modern

**Java 5 on 2004-09-30** is arguably the most important single release in the language's history, because it is the point where Java stopped looking like an awkward C++ derivative. It added generics, annotations, enums, autoboxing, the enhanced for loop, varargs, and static imports.

Main.java
Run Online
// Java 5 generics: type safety without casting
List names = new ArrayList();
names.add("alpha");
// Java 5 enums
enum Status {
    NEW, RUNNING, DONE
}// Java 5 autoboxing, no explicit new Integer(...)
Integer count = 1;

The effect was that Java 5 code is recognisably modern Java. The gap between the 1.x style and the 5 style is the largest stylistic break in the language's history.

5. The Acquisition, and What It Changed

Oracle completed its acquisition of Sun Microsystems in **January 2010**. The deal guaranteed the continued funding of the Java platform and in particular the HotSpot JVM, and under Oracle the language moved onto a predictable release schedule rather than the long, irregular gaps that had characterised the previous decade.

There was also sustained community concern during this period, mostly about licensing changes to Oracle's JDK builds. The practical response was OpenJDK, which became the reference implementation, and today the major distributions such as Temurin, Corretto, and Zulu all build from it. In practice, almost all Java in production today runs on OpenJDK code, regardless of vendor.

6. Java 7, 8, and the Turn Toward Modern Syntax

**Java 7** brought the diamond operator and try-with-resources, which quietly removed a large amount of noisy code.

**Java 8 on 2014-03-18** was the first LTS release under the modern world, with class file version **52.0**, and it is the most consequential release since Java 5. Lambda expressions, method references, the Stream API, java.time, and default methods all arrived at once.

Main.java
Run Online
List.of("alpha", "beta", "gamma").stream() .filter(s -> s.length() > 4) .map(String::toUpperCase) .forEach(System.out::println);

Java 8 also started the long support story that matters operationally. It is EOL in 2027, which makes it the oldest currently supported LTS and unusually long-lived for a release line.

7. The Six-Month Cadence

In **September 2017** JDK 9 shipped, introducing the module system, jshell, and JEP 280 string concatenation. More importantly for planning purposes, it inaugurated the six-month feature release cadence that still governs Java today, with a feature release every March and September and a long-term support release roughly every two years.

The practical effect is that Java development is now incremental rather than event-driven. A feature you read about has a known minimum version, and an LTS gives a multi-year support window.

Architecture Diagram
RELEASE TRAIN
   ┌──────────────────────────────────────────────────────────────┐
   │  every 6 months:  9, 10, 11, 12, ... 26, 27   (features)    │
   │  every ~2 years:  8, 11, 17, 21, 25          (LTS + support) │
   └──────────────────────────────────────────────────────────────┘

8. The LTS Line, and Where It Stands Now

This matters more than any single feature, so it is worth getting exactly right. The current support picture, as of late 2026:

LTSReleasedClass fileSupport ends
Java 82014-03-1852.02027-07
Java 112018-09-2555.02027-10
Java 172021-09-1461.02027-10
Java 212023-09-1965.02029-12
Java 252025-09-1669.02030-09

**Java 25 is the current LTS** and **Java 27** is the current feature release. Java 8, 11, and 17 all reach end of support in 2027, which is a real planning deadline for anyone still on them.

The class file version is worth noticing, because it is the mechanism behind backward compatibility. Each release increments it, and a newer JVM can always run older bytecode.

ReleaseClass file major
Java 1.045
Java 1.246
Java 549
Java 852
Java 953
Java 1155
Java 1761
Java 2165
Java 2569
Java 2771

9. Language Milestones You Will Actually Meet

Rather than every release, these are the ones that change how you write code.

VersionFeatureStatus
5Generics, enums, autoboxing, for-eachFinal
7Diamond operator, try-with-resourcesFinal
8Lambdas, streams, java.timeFinal
9Module system, jshellFinal
11HTTP client, var in lambda paramsFinal
14Switch expressionsFinal
15Text blocksFinal
16Records, instanceof patternsFinal
17Sealed classesFinal
21Virtual threads, record patterns, pattern switchFinal
25Scoped values, compact object headersFinal

Text blocks are a good example of what a "final" feature looks like in practice, and they arrived in 15:

Main.java
Run Online
String query = """
        SELECT id, name
        FROM customers
        WHERE active = true""";

10. The Feature That Is Still Not Done: Structured Concurrency

It is easy to read "virtual threads, Java 21" and assume the concurrency story was completed there. It was not. **Structured Concurrency has been repeatedly previewed and never finalized**, and it is the clearest illustration of how the JDK process actually works.

Main.java
Run Online
JEP 428 Java 19 incubating API JEP 437 Java 20 second incubator JEP 453 Java 21 first preview JEP 462 Java 22 second preview JEP 480 Java 23 third preview JEP 499 Java 24 fourth preview JEP 505 Java 25 fifth preview JEP 525 Java 26 sixth preview JEP 533 Java 27 seventh preview

The reason it keeps changing is that structured concurrency is genuinely hard to get right, since a wrong API here becomes permanent and hard to remove. Virtual threads, by contrast, *are* final in Java 21.

FeatureFirst appearedCurrent status
Virtual threads21Final
Record patterns21Final
Pattern matching for switch21Final
Scoped values25Final
Structured concurrency19 (incubating)Preview in 27, seventh iteration
Primitive types in patterns23Preview in 27

The lesson is worth stating plainly: a feature listed for a release may still be a preview in that release, so always check whether something is final before designing around it.

11. Backward Compatibility: The Real Story

The single most consequential thing about Java's history is not any feature, it is that **old bytecode keeps running**. Code written for Java 1.0-era syntax still compiles and runs on a Java 25 JVM, which is why a long-lived enterprise system can be upgraded in JDK steps rather than rewritten.

The example accompanying this topic demonstrates exactly that, mixing 1996-era array-and-StringBuilder code, 2004 generics, 2014 streams, and 2021 records in a single class that compiles and runs unchanged.

Main.java
Run Online
// all of this compiles together on a modern JDK
String[] classic = {
    "one", "two"
};
// 1996 style
List names = new ArrayList();
// Java 5
Stream.of("a").filter(s -> s.length() > 0) // Java 8
.forEach(System.out::println);
record Release(String what, int since) {
} // Java 16

This compatibility is also a constraint, not just a benefit. It is why Object.finalize() could be deprecated in 9 but survived for years, and why removals like the Applet API took from deprecation in 17 all the way to removal in 26.

Main.java
Run Online
Applet API: deprecated for removal Java 17(JEP 398)↓removed Java 26(JEP 504) SecurityManager: deprecated for removal Java 17(JEP 411)↓not yet removed, but unusable in practice

12. Timeline Summary

YearEvent
1991Green Project begins at Sun; the language is named Oak
1995Renamed from Oak to Java
1996-01-23Java 1.0 released, class file 45.0
1997Java 1.1 adds JDBC, RMI, reflection
1998-12-04Java 1.2, Collections and Swing, era of J2EE begins
2004-09-30Java 5 (Tiger), generics and enums
2010Oracle completes acquisition of Sun Microsystems
2014-03-18Java 8 LTS, lambdas and streams
2017-09-21Java 9, module system, six-month cadence begins
2018-09-25Java 11 LTS, first LTS on the new schedule
2021-09-14Java 17 LTS, sealed classes
2023-09-19Java 21 LTS, virtual threads
2025-09-16Java 25 LTS, current LTS
2026-09-15Java 27, current feature release

13. What the History Teaches

Three lessons carry forward from this timeline. First, Java's most valuable property was never any individual feature; it is the combination of static typing, memory safety, and backward compatibility, which together make it viable for systems measured in decades. Second, the release process is now predictable enough that version numbers are part of everyday planning, so you should always target an LTS and know when it expires. Third, "shipped in version X" does not mean "final", and the structured-concurrency record of eight iterations since 19 is the clearest proof.

Runnable Code Example: The Story of Java

Java 17+
Main.java
Run Online
import java.util.stream.Stream;
// This class deliberately mixes eras of Java to show backward compatibility.
// Every line below compiles on a modern JDK, some of it unchanged since
1996.public class JavaEvolution {
    // Java 8 (2014): lambdas, method references, streams
    static Stream<String> modern() {
        return Stream.of("alpha", "beta", "gamma").filter(s -> s.length() > 4);
    } // Java 5 (2004): generics and autoboxing
    static int count(java.util.List<String> items) {
        return items.size();
    } public static void main(String[] args) {
        // 1996 era: plain arrays and StringBuilder still work unchanged
        String[] classic = {
            "one", "two"
        };
        StringBuilder sb = new StringBuilder("built the old way: ");
        for (String s : classic) {
            sb.append(s).append(' ');
        } System.out.println(sb);
        // 2004 era
        System.out.println("Java 5 style: " + count(java.util.List.of(classic)) + " items");
        // 2014 era
        modern().forEach(System.out::println);
        // 2021 era: records, sealed types, HexFormat all on the same JDK
        System.out.println("Java 17 style: " + new Release("sealed and records", 17));
        System.out.println("hex: " + java.util.HexFormat.of().formatHex("Hi".getBytes()));
        // Ask the running JVM what it actually is
        System.out.println("running: Java " + Runtime.version().feature() + ", class file version " + System.getProperty("java.class.version"));
    } record Release(String what, int since) {
        @Override public String toString() {
            return what + " (since " + since + ")";
        }
    }
}

Common Java Technical Interview Questions & Answers

Interview Prep
Q1

Where did Java come from?

From the Green Project at Sun Microsystems, started in 1991 and led by James Gosling with Mike Sheridan and Patrick Naughton. The language was originally called Oak and was aimed at consumer electronics, specifically set-top boxes and embedded appliances, because those devices shipped with different processors and software was expected to move between them. Java's answer was to insert a virtual machine so the platform-specific layer was written once per device rather than once per application.
Q2

Why was it renamed from Oak to Java?

Because the consumer electronics market the project targeted did not materialise, and the name Oak had trademark problems in any case. The project was rescued by a different target: the World Wide Web, which had exactly the property Oak was designed for, since it spans heterogeneous hardware and Java's portability meant one program ran on whatever machine the visitor had. Java 1.0 shipped on 1996-01-23 with class file version 45.0.
Q3

Which Java release mattered most, and why?

Most people pick Java 5, released 2004-09-30, because it is the point where Java stopped looking like an awkward C++ derivative. Generics, annotations, enums, autoboxing, the enhanced for loop, and varargs all arrived together. Some would argue for Java 8, released 2014-03-18, because lambdas and the Stream API changed how ordinary code is written. Either way, the 1.x to 5 gap is the largest stylistic break in the language's history.
Q4

What did Oracle's acquisition of Sun change?

The deal closed in January 2010. The practical effect was predictable releases: under Oracle the platform moved from long irregular gaps to a scheduled cadence, which began with JDK 9 in September 2017. There was also sustained controversy about JDK licensing, and the practical response was OpenJDK, which became the reference implementation. Today nearly all production Java runs on OpenJDK builds such as Temurin, Corretto, or Zulu, regardless of vendor.
Q5

What is the current Java release situation?

As of late 2026, Java 25 is the current long-term support release, having shipped on 2025-09-16, and Java 27 is the current feature release from 2026-09-15. Java 8, 11, and 17 all reach end of support during 2027, which matters if you are still on any of them. Note that Java 8 is unusually long-lived, with support running to 2027, which makes it the oldest currently supported LTS.
Q6

Is Structured Concurrency a Java 21 feature?

It is not, and this is a common misstatement. It first shipped in Java 19 as an incubating API, then previewed in 21, and has been re-previewed every release since. It reached its seventh preview in Java 27. Virtual threads, by contrast, are genuinely final in Java 21. The reason structured concurrency keeps changing is that it is hard to design correctly, and an API that shipped prematurely would be effectively permanent.
Q7

What is backward compatibility, and why does it matter so much?

It means bytecode compiled for an older JDK keeps running on a newer JVM. Code written in Java 5 style still compiles and runs on Java 25. This is unusual among mainstream languages, and it is why a long-lived enterprise system can be upgraded in JDK steps rather than rewritten. It is also a constraint, because features cannot simply be deleted; the Applet API sat deprecated for removal from Java 17 until it was finally removed in Java 26.
Q8

What happened to applets?

They are gone. They were the reason for Java's first burst of visibility in the mid-1990s, driving enormous developer interest, but the durable enterprise adoption of Java came through server-side software rather than through applets. The API was deprecated for removal in Java 17 by JEP 398 and finally removed in Java 26 by JEP 504, so java.applet.Applet still exists on 17 but is deprecated, and is absent from 26.
Q9

What happened to SecurityManager?

It was deprecated for removal in Java 17 by JEP 411, and it is functionally unusable for new code. This matters because it was the basis for the traditional claim that Java is a secure, sandboxed language. What survives is narrower but still valuable: the bytecode verifier, array store checks, and the absence of pointer arithmetic. What does not survive is in-process sandboxing, so real isolation now comes from containers or separate processes.
Q10

How does the class file version relate to compatibility?

Each release increments it, and a newer JVM can always run older bytecode. Java 1.0 was version 45, Java 5 was 49, Java 8 was 52, Java 11 was 55, Java 17 was 61, Java 21 was 65, Java 25 is 69, and Java 27 is 71. Because the number only ever increases, a newer runtime always accepts older classes, which is the mechanism behind backward compatibility. It also means code compiled on a newer JDK will not run on an older JVM, so build targets should be set deliberately.
Q11

Why does the six-month cadence matter in practice?

Because it turns Java releases into a plan rather than an event. Features arrive on a known schedule, LTS releases give a multi-year support window, and you can reason about when support ends well in advance. The practical discipline that follows is to target an LTS for production, pin the build to that version explicitly, and check the minimum version of any feature before relying on it.
Q12

If you had to summarise Java's history in one lesson, what would it be?

That Java's greatest achievement is durability rather than novelty. Individual features come and go, and some are still being reworked after eight iterations, but the combination of static typing, memory safety, and backward compatibility is what let Java become the default for large systems that must be maintained for a decade or more. That is why it remains dominant in enterprise backends despite being thirty years old.

Key Takeaways, Best Practices & Clean Code Rules

Java Best Practice & Production Rules

Target a long-term support release and record its end-of-life date in the project, because support is what you are actually buying: Java 25 is the current LTS and Java 27 the current feature release, while Java 8, 11, and 17 all reach end of support during 2027, so a project pinned to any of them needs a scheduled upgrade rather than a discovery later. Pin the build to a specific JDK version explicitly instead of relying on whatever the developer machine happens to have, since the six-month cadence means a newer compiler can silently accept code that will not run on the JVM you deploy to, and the class file version increases with every release. Check whether a feature is final before designing around it, because a feature being listed for a release does not mean it shipped in final form; Structured Concurrency has been previewed seven times between Java 21 and Java 27, whereas virtual threads from 21 are final. Rely on backward compatibility as a deliberate constraint rather than assuming it, which means keeping public APIs and class file targets stable, and do not build on anything deprecated for removal, since removal can follow years later as the Applet API did between 17 and 26. Prefer an LTS for production and a current feature release only when you want to evaluate something new, and be explicit in your build about which of the two you are targeting. Finally, treat deprecation warnings as scheduling information rather than noise, because the JDK gives long runways before removal and the practical failure mode is being surprised by a removal after years of building on a deprecated API.
We value your privacy & transparency

OperateTools uses cookies and local storage to ensure basic tool functionality, preserve preferences, and analyze aggregated traffic. We never sell your personal data or index your document files. Learn more in our Privacy Policy.