Command Palette

Search for a command to run...

[Java Basics] What is Java? History, Key Features, and Why It Is Still Worth Learning

Java is two things wearing one name: a programming language, and a runtime platform. Most of the confusion around it — including the argument about whether it is fast, free, or dying — comes from treating those two as the same thing.

Everything in this article was checked against a real toolchain: OpenJDK 21.0.6 on macOS/aarch64. Version strings, compiler errors and timings are copied out of a terminal, not recalled from memory.

What is Java? The Java language and platform explained

The order below is: what Java is, how it got here, what makes it distinctive, where it actually runs in production, how it compares with its neighbours, and which of the usual complaints hold up.

What is Java?

Java is a statically typed, object-oriented, general-purpose programming language that compiles to bytecode rather than to machine code. That bytecode is executed by the Java Virtual Machine — a program that has been ported to every mainstream operating system and CPU architecture.

The language/platform split matters more than it sounds. The language is the syntax and the type system you write. The platform is the JVM, the standard library, and the class-file format the two agree on. They are separable in both directions: Kotlin, Scala, Clojure and Groovy compile to the same bytecode and run on the same JVM without a line of Java source, and Java source can be compiled ahead of time into a native executable that never loads a conventional JVM at all.

TermWhat it actually is
Java (the language)The syntax, type system and semantics you write in .java files
BytecodeA portable instruction set, stored in .class files
JVMThe program that loads bytecode and executes it on one specific OS and CPU
Java SEThe specification that ties the three together: language, virtual machine, and standard library API

So "learning Java" is really three things at once: the language, the standard library, and the tooling. This series takes them in that order.

A short history of Java, with real dates

Java did not start as a web or server language. It started as an attempt to control set-top boxes.

Thirty years of releases, and the point where the cadence changed

The releases that matter, and where the six-month cadence begins:

YearEvent
1991The Green Team at Sun Microsystems, led by James Gosling, starts a language called Oak, aimed at consumer devices and set-top boxes
1995Oak is renamed Java — the name was already trademarked — and announced publicly on 23 May 1995 alongside the HotJava browser
1996JDK 1.0 ships on 23 January 1996
1998J2SE 1.2, marketed as "Java 2": Swing and the Collections Framework
2004J2SE 5.0: generics, annotations, enums, the enhanced for loop
2006–2007Sun open-sources the implementation as OpenJDK, under GPLv2 with the Classpath Exception
2010Oracle acquires Sun Microsystems and inherits stewardship of Java
2014Java 8: lambdas, streams, the new date and time API. The most widely deployed release ever made
2017Java 9: the module system, and the start of the six-month release cadence
2018Java 11, the first LTS under the new cadence
2021Java 17 LTS: sealed classes, records, pattern matching for instanceof
2023Java 21 LTS: virtual threads, record patterns, pattern matching for switch
2025Java 25, the LTS following 21, released in September

Before 2017 a major Java release arrived every two to five years. Since Java 9 a feature release ships every six months, in March and September, and most of those releases are supported only until the next one appears. Every two years one release is designated LTS (long-term support) and receives security and bug-fix updates for years afterwards. The LTS line is 8, 11, 17, 21, 25.

In practice, Java 21 is the LTS that most new projects target today. Java 25 is newer and adoption is climbing, but 21 remains the safe default for a greenfield service; Java 17 is everywhere in code written since 2021; and Java 8 still runs an enormous amount of production software that nobody has budget to migrate. When a tutorial says "Java", assume it means 17 or 21 unless it says otherwise.

Write once, run anywhere: what actually happens

The slogan is real, and the mechanism behind it is simple. javac does not produce machine code. It produces a .class file containing bytecode — instructions for an abstract machine that does not physically exist. A JVM built for your specific OS and CPU loads that file and translates it into real instructions as the program runs.

One source file compiles to one bytecode artifact, which three different JVMs on Windows, macOS and Linux all execute to the same result

Here is the smallest program that makes the point — it asks the platform it is running on to identify itself:

public class WhereAmI {
    public static void main(String[] args) {
        System.out.println("Java version: " + System.getProperty("java.version"));
        System.out.println("Running on:   " + System.getProperty("os.name")
                                            + " / " + System.getProperty("os.arch"));
    }
}

Compiled and run on the machine used for this article:

Java version: 21.0.6
Running on:   Mac OS X / aarch64

The interesting part is what happens when a different JVM loads the same file. Compiling once for Java 17 and then running the resulting .class on two different virtual machines, without recompiling in between:

$ java -cp out17 WhereAmI
Java version: 21.0.6
Running on:   Mac OS X / aarch64

$ /opt/homebrew/.../openjdk@17/.../bin/java -cp out17 WhereAmI
Java version: 17.0.14
Running on:   Mac OS X / aarch64

One artifact, two runtimes, no rebuild. Extend that to a different operating system and a different CPU and you have the whole idea.

The compatibility runs one way only. A .class file compiled by JDK 21 with its default target will not load on an older JVM, and the error message says exactly why:

Error: LinkageError occurred while loading main class WhereAmI
	java.lang.UnsupportedClassVersionError: WhereAmI has been compiled by a more recent version of the Java Runtime (class file version 65.0), this version of the Java Runtime only recognizes class file versions up to 61.0

Bytecode is also not magic. Anything that reaches outside the JVM — native libraries, file path separators, the platform default character encoding, OS-specific APIs — can still behave differently per platform. "Write once, run anywhere" is a promise about the bytecode, not about every line of code you can write on top of it.

The characteristics that define Java

Compiled to bytecode, executed by a virtual machine. Covered above. This is the single design decision that everything else follows from: portability, the JIT compiler, the garbage collector, and the fact that four other popular languages target the same runtime.

Statically and strongly typed. Every variable has a type that is fixed and checked before the program runs. Type errors are compile errors, not surprises in production at 3 a.m. Assigning a string to an int never reaches the JVM:

Typed.java:3: error: incompatible types: String cannot be converted to int
        int count = "twelve";
                    ^
1 error

This is the trade Java makes: more up-front ceremony, in exchange for an entire class of bugs that a dynamically typed language only discovers at runtime. It pays off in proportion to how large the codebase is and how many people touch it.

Automatic memory management. You allocate objects; you never free them. A garbage collector reclaims what is no longer reachable. Java 21 defaults to the G1 collector — visible in the JVM's own log — and ships several others (Parallel, Serial, ZGC, Shenandoah) for different latency and throughput targets. The cost is that a collection pause is something you have to think about in latency-sensitive systems; the benefit is that use-after-free and double-free bugs do not exist in ordinary Java code.

[0.006s][info][gc] Using G1

Object-oriented, with few escape hatches. Every method and every field lives inside a class or an interface. There are no free-floating functions and no global variables. The only values that are not objects are the eight primitive types (int, long, double, boolean and friends). This is prescriptive by design — it makes large codebases predictable, and it makes small scripts more verbose than they need to be.

Multithreaded from the first release. Threads, locks and a memory model have been part of the language and the standard library since 1.0, not bolted on by a library. Java 21 added virtual threads: lightweight threads scheduled by the JVM rather than the operating system, which lets a server handle a very large number of concurrent blocking operations without a thread pool per connection.

Backward compatible to an unusual degree. Old bytecode keeps running on new JVMs. Compiling for Java 8 with a Java 21 compiler still works, produces class file version 52.0, and that file runs on the modern JVM unchanged:

$ javac --release 8 -d out8 WhereAmI.java
warning: [options] source value 8 is obsolete and will be removed in a future release
warning: [options] target value 8 is obsolete and will be removed in a future release
warning: [options] To suppress warnings about obsolete options, use -Xlint:-options.
3 warnings

$ file out8/WhereAmI.class
out8/WhereAmI.class: compiled Java class data, version 52.0 (Java 1.8)

$ java -cp out8 WhereAmI
Java version: 21.0.6
Running on:   Mac OS X / aarch64

Almost no other ecosystem takes compatibility this seriously. It is the main reason enterprises standardised on Java, and also the main reason the language evolves more slowly than its competitors.

A large standard library, and a larger ecosystem. The Java 21 runtime image ships 69 modules covering collections, I/O, networking, HTTP, cryptography, concurrency, date and time, XML and JDBC. Outside it, Maven Central is one of the largest package repositories in software, and the build tools, test frameworks, profilers and debuggers around the JVM are unusually mature.

Where Java is actually used today

DomainReal systems
Enterprise backendsSpring Boot, Jakarta EE, Quarkus and Micronaut — the default stack for corporate REST and gRPC services
AndroidThe Android framework API is a Java API; app code is Java or Kotlin, compiled to DEX bytecode and run by the ART runtime
Big data and streamingHadoop, Spark, Kafka, Flink, Elasticsearch/OpenSearch, Cassandra and HBase are all JVM projects
Fintech and bankingCore banking, payment switching, clearing and trading systems; long-lived, heavily audited, compatibility-sensitive
Desktop and gamesMinecraft: Java Edition; the JetBrains IDEs, including IntelliJ IDEA and Android Studio
Test and build toolingJUnit, Selenium, Maven, Gradle, Jenkins, SonarQube

Two patterns explain that list. Java dominates wherever a process runs for weeks and throughput matters more than startup time — which is exactly the shape of a backend service, a stream processor or a search cluster. And it dominates wherever code has to keep working for a decade, because backward compatibility is a feature you only value after you have been burned by its absence. Netflix, LinkedIn, Uber and Alibaba have all published extensively about operating large JVM fleets.

Java vs Python vs JavaScript vs C#

JavaPythonJavaScriptC#
TypingStatic, strong, explicit (var infers locals)Dynamic, strong; type hints are not enforced at runtimeDynamic, weak, with implicit coercion; TypeScript adds static types at build timeStatic, strong, explicit
ExecutionBytecode, JIT-compiled by the JVMBytecode, interpreted by CPythonJIT-compiled by V8 / SpiderMonkey / JavaScriptCoreIL, JIT-compiled by the CLR
StartupSlowest of the four; tens of milliseconds before main runsFastFastFast, and AOT compilation is mature
Peak throughputVery high once warmed upLowest; heavy work is delegated to C extensionsHigh for the workloads engines are tuned forVery high, broadly comparable to Java
VerbosityHighest of the fourLowestLowBetween Java and Python
Typical domainBackends, Android, data infrastructureScripting, data science, ML, automationBrowsers, Node.js backendsWindows and enterprise software, Unity games, backends
Learning curveModerate; a lot of ceremony before it pays offGentleGentle at first, sharp laterModerate, very similar to Java

Where Java genuinely loses:

  • Verbosity. Printing a line of text requires a class, a main method with a fixed signature, and an explicit type on almost everything. Python does it in one line. Recent releases have trimmed the boilerplate considerably, but the floor is still higher.
  • Startup time. Measured on the machine used here: 25 runs of a trivial Java program after five warm-up runs took 24.6 ms at best and 25.9 ms at the median, against 1.8 ms and 2.2 ms for an equivalent C binary. Disabling class-data sharing with -Xshare:off pushes the Java figure to 35.7 ms. For a server that runs for a month, irrelevant. For a CLI tool invoked in a shell loop, or a short serverless function billed per invocation, it is the dominant cost.
  • Memory footprint. A JVM at idle costs more RAM than an equivalent Go or Python process, because it carries a heap, metaspace, JIT-compiled code and its own thread stacks.
  • Pace of change. Records arrived in Java 16 and pattern matching for switch in Java 21 — features other languages had shipped years earlier. Compatibility has a price, and this is it.

Myths about Java that refuse to die

Myth: Java is slow

Half true, and the half that is true is not the half people mean.

The JVM starts by interpreting bytecode, then a JIT compiler watches which methods run often and compiles those to native machine code while the program is running. The same loop, run eight times in one process on OpenJDK 21.0.6, shows both the warm-up and the payoff:

Run modeRound 1Round 2Round 3Rounds 6–8
Default (JIT enabled)13.6 ms13.5 ms8.1 ms~9.2 ms
-Xint (interpreter only)129.0 ms121.8 ms128.8 ms

Indicative numbers from one machine, but the shape is the point: with the JIT disabled the workload is more than 13 times slower, and even with it enabled the first two rounds are noticeably slower than the rest because compilation has not finished yet. A long-running Java server spends almost all of its life in the right-hand column, at speeds comparable to native code.

The tier transitions behind those numbers are visible with -XX:+PrintCompilation: interpreter first, then C1 at tier 3, then C2 at tier 4.

A JIT warm-up trace: the same method starts interpreted, is compiled by C1 at tier 3 and then C2 at tier 4, with per-run times falling, next to the -Xint interpreter-only baseline

What is slow is the beginning. The JVM has to start, load and verify classes, and warm up before it reaches full speed — the ~25 ms of process startup measured above, plus however long your hot paths take to get compiled. "Java is slow" and "Java is fast" are both correct; which one applies depends entirely on how long your process lives.

They are not. They share four letters, a C-inspired syntax for braces and semicolons, and nothing else.

JavaScript was created at Netscape in 1995 by Brendan Eich and renamed from LiveScript to JavaScript as a marketing decision, while Netscape and Sun were partners. From there the two diverged completely: different type systems, different memory and concurrency models, different standard libraries, different object models (classes versus prototypes), and different governance — the JDK Enhancement Proposal process versus Ecma TC39.

Knowing one does not teach you the other. The transferable part is general programming, not the language.

Myth: Java is dying

It has been declared dying since roughly 2005. Meanwhile: a feature release has shipped every six months without interruption since 2017, two LTS releases have landed since 2021, Android's framework API is Java, and most of the world's data infrastructure runs on the JVM.

The honest version is narrower. Java is no longer the automatic first choice for a new startup, it has slipped from the top of language popularity indices, and it lost the scripting and data-science ground permanently to Python. But the installed base is enormous, migration off it is expensive, and hiring demand tracks the installed base rather than the hype cycle. "Not the most fashionable" and "dying" are very different claims.

Myth: Java is not free

Java itself is free. OpenJDK — the reference implementation that essentially every distribution is built from — is open source under GPLv2 with the Classpath Exception, which explicitly allows you to ship closed-source applications on it.

What can cost money is a specific vendor build with commercial support attached. Oracle's own JDK is distributed under Oracle's terms, and the confusion dates to January 2019, when Oracle stopped providing free public updates for Oracle JDK 8 for commercial use. That was a licence change for one vendor's binaries, not for the language.

Free, production-ready builds include Eclipse Temurin (Adoptium), Amazon Corretto, Azul Zulu, Microsoft Build of OpenJDK, Red Hat's build, SapMachine, and Oracle's own GPL-licensed builds from jdk.java.net.

⚠️ The licence attaches to the build you downloaded, not to "Java". Before deploying, check which vendor's JDK is actually in your container image.

Is Java still worth learning?

Yes, with a clear picture of what for.

Learn it if you are aiming at backend engineering at scale, Android, data infrastructure, or fintech — those are the places Java is not merely present but dominant. The static type system and the tooling built on it (reliable refactoring, precise navigation, errors caught at compile time) pay for their ceremony as codebases and teams grow. And the JVM knowledge transfers: Kotlin, Scala and Clojure all reuse the same runtime, the same libraries and the same debugging tools.

Do not start with Java if you want a website live this weekend, if you are heading for data science and machine learning, or if your target is short-lived processes where startup dominates.

One correction worth making up front: modern Java is not the language people complain about. Records, var, text blocks, switch expressions, sealed types and virtual threads have all landed since 2018. Criticism quoting a textbook from 2010 is describing a language that no longer exists.

FAQ

Is Java the same as JavaScript?

No, and they are not related. Java is a statically typed, compiled, JVM-based language used mostly for backends and Android. JavaScript is a dynamically typed language that runs in browsers and in Node.js. The shared name was a marketing decision in 1995.

Which Java version should I learn?

Java 21. It is the LTS most new projects target, and everything you learn on it applies to 17 and 8 as well — the fundamentals have not changed, only the syntax available on top of them. Learning on an old version and upgrading later is harder than the reverse.

Is Java free to use?

Yes. OpenJDK is licensed under GPLv2 with the Classpath Exception, and free builds from Adoptium, Amazon, Azul, Microsoft and others are production-ready. Only certain commercially supported vendor builds — Oracle's in particular — carry licensing terms worth reading before you deploy.

How long does it take to learn Java?

Syntax and basic object-oriented programming take a few weeks of consistent practice. Being productive on a real Spring Boot codebase takes months, because the ecosystem — build tools, dependency injection, ORM, testing, deployment — is far larger than the language. The language is the short part.

Is Java a good first programming language?

It is defensible but not the gentlest. Static types and precise compiler errors genuinely help beginners, because mistakes surface immediately with a clear explanation. Against that, you meet classes, access modifiers and public static void main on line one, before any of it means anything. If your goal is backend work, starting with Java is a reasonable choice.

Do I need Java to build Android apps?

Kotlin is the default for new Android development, but the Android framework API is a Java API, an enormous amount of Android documentation and existing code is Java, and Kotlin was designed to interoperate with it. Java knowledge transfers directly; Java-free Android work is rare.

Conclusion

Java is a statically typed, object-oriented language that compiles to bytecode, plus a virtual machine that runs that bytecode everywhere. It began as Oak at Sun in 1991, shipped as JDK 1.0 in 1996, moved to Oracle in 2010, and has released every six months since 2017, with Java 21 as the LTS most new work targets. It is verbose and slow to start, and it is exceptionally fast once warm, exceptionally stable across versions, and entrenched in backends, Android and data infrastructure. All of those are true at once.

The next article installs it and takes apart the acronyms: what a JDK actually contains, what a JRE is, what the JVM does, and which one you need on your machine.

Related Posts

[Java Basics] Arrays in Java: Declaring, Initializing and Traversing

A complete guide to one-dimensional arrays in Java - every declaration form, default values, the length field, indexing and ArrayIndexOutOfBoundsException, indexed and for-each traversal, the reference trap, real copies with Arrays.copyOf and System.arraycopy, and Arrays.equals, all compiled and run on JDK 21.

[Java Basics] HashMap in Java: put, get, merge and the hashCode/equals Contract

How HashMap works in Java - put, get, containsKey, remove, getOrDefault, putIfAbsent, merge and computeIfAbsent, iterating with entrySet, buckets and hash distribution, and the hashCode/equals contract that decides whether a key can be found again.

[Java Basics] JDK, JRE and JVM: The Difference and How to Install Java

The precise difference between JDK, JRE and JVM, why the standalone JRE download is gone, how to install Java 21 on macOS, Windows and Linux, and how to read UnsupportedClassVersionError.

[Java Basics] Loops in Java: for, while and do-while

Loops in Java explained by running them: the exact execution order of a for header, while vs do-while, the enhanced for and why it cannot write back, off-by-one errors against length, and the three ways to write an infinite loop.