For almost three decades, Java has been one of the world's most widely used languages for building software that has to keep running for years, on different machines and under real load. Before writing a single line of code it is worth understanding what problem Java set out to solve, how it manages to run on any operating system without recompiling, and what exactly the acronyms JDK, JRE and JVM mean, since they will show up in every tutorial, every error message and every job posting. This lesson gives you that mental map. It also introduces BiblioTech, the project you will build from start to finish throughout the course, turning every abstract concept into something that actually works.
Contents
- What Java is and what problems it solves
- The WORA principle: write once, run anywhere
- JDK, JRE and JVM: three pieces that get confused constantly
- The language's features, explained
- A brief history and the LTS release calendar
- Where Java is used today
- The course project: BiblioTech
- Common Mistakes and Tips
- Exercises
- What Java is and what problems it solves
Java is a general-purpose, object-oriented, statically typed programming language, together with a runtime platform (the virtual machine and its standard library). This dual nature matters: when somebody says "I work with Java" they are not referring only to a syntax, but to a whole ecosystem of tools, libraries and servers that all rely on the same virtual machine.
Java was born at Sun Microsystems in the early nineties, at a time when writing portable applications was painful. The specific problems it attacked were:
- Dependence on the operating system and the processor. A program written in C was compiled to the native instructions of one specific architecture. Moving it from Windows to Solaris meant recompiling and, almost always, rewriting parts of it. Java introduced an intermediate format (bytecode) that runs the same way on any machine with a JVM.
- Manual memory management. In C and C++ the programmer allocates and frees memory by hand. Forgetting to free causes leaks; freeing twice or using an already freed pointer causes corruption that is hard to debug. Java delegated all of that to an automatic garbage collector.
- Pointer arithmetic and overflows. Java removed programmer-manipulable pointers and added bounds checking on indexed memory access. Many classic security flaws simply cannot happen.
- The lack of a rich standard library. From the very beginning Java shipped with classes for text, dates, collections, networking, threads and input/output. There was no need to hunt for a different library for each operating system.
The result is a language designed for long-lived software: enterprise applications maintained for ten or fifteen years, by teams whose members come and go, where readability and stability are worth more than syntactic brilliance.
- The WORA principle: write once, run anywhere
Java's historic slogan is WORA (Write Once, Run Anywhere): you write the code once and it runs on any platform without changes. This is not magic, it is a direct consequence of how a Java program is compiled and executed.
The journey of your code
- You write a source code file with the
.javaextension. It is plain text, readable by humans. - The
javaccompiler translates it into bytecode, an intermediate instruction set, and saves it in a.classfile. That bytecode is not specific to Windows, Linux or macOS: it is specific to the Java virtual machine. - The JVM (Java Virtual Machine) installed on each system reads that
.classfile and runs it. Internally, a JIT (Just-In-Time) compiler translates the most heavily used parts of the bytecode into native instructions for the real processor, so that performance stays high.
flowchart TD
A["BiblioTechApp.java<br/>(source code, text)"] -->|"javac"| B["BiblioTechApp.class<br/>(bytecode, portable)"]
B --> C{"JVM"}
C --> D["JVM on Windows<br/>→ x86 instructions"]
C --> E["JVM on Linux<br/>→ x86/ARM instructions"]
C --> F["JVM on macOS<br/>→ ARM instructions (Apple Silicon)"]
The key lies in that final fork: what you distribute is the bytecode, and what changes between systems is the JVM, not your program. When you compile the file BiblioTechApp.java on your laptop and send the resulting .class to a Linux server, that server runs it without recompiling anything.
The honest caveats of WORA
WORA is real, but it is worth knowing its limits from the start:
- A program compiled with a JDK 21 does not run on a JVM 17. Compatibility is forward (a newer JVM runs older bytecode), not backward. That is why the version matters so much.
- If your code uses paths like
C:\data\books.txtor calls system commands, you have introduced a platform dependency yourself. Java gives you the tools to avoid it, it does not force you to use them. - Details such as the default character encoding or the line separator have historically varied between systems. Modern Java (17+) has unified much of this, for instance by fixing UTF-8 as the default encoding from Java 18 onwards.
- JDK, JRE and JVM: three pieces that get confused constantly
This is probably the number one source of confusion for beginners. The three acronyms describe concentric layers: the JDK contains the JRE, and the JRE contains the JVM.
| Acronym | Full name | What it contains | What it is for | Do you need it? |
|---|---|---|---|---|
| JVM | Java Virtual Machine | The engine that loads and runs bytecode, the garbage collector and the JIT compiler | Running bytecode by translating it into native instructions | Yes, but it is never installed on its own |
| JRE | Java Runtime Environment | The JVM + the standard class library (java.lang, java.util, java.io…) |
Running already compiled Java applications | Yes, it comes bundled in the JDK |
| JDK | Java Development Kit | The JRE + development tools: javac (compiler), jshell, jar, javadoc, jdb (debugger), jlink |
Writing, compiling and packaging programs | Yes: this is what you will install |
The practical rule is simple: as a developer you install the JDK and forget about the rest. The standalone JRE stopped being distributed from Java 11 onwards; today it is assumed that whoever runs Java has a full JDK or a trimmed-down image created with jlink.
An analogy that usually helps: the JVM is a car's engine, the JRE is the complete car ready to drive, and the JDK is the car plus a workshop with every tool needed to build new cars.
- The language's features, explained
Lists of "Java features" tend to be useless because they pile up adjectives without explaining them. Let's look at what each one means in practice.
Object-oriented
In Java, code is organised into classes: templates that group data together with the operations on that data. Instead of having, on one side, a few loose variables holding the title, the author and the ISBN of a book, and on the other side some functions that operate on them, you define a Book class that holds both. That lets code grow in an orderly way: when the system has two hundred different entities, each one knows how to look after its own data.
In this first module you will work only with loose variables inside a main, precisely so that you feel how uncomfortable that is. In module 3 you will turn those variables into classes and see the difference with your own eyes.
Statically typed
Every variable declares what type it is, and the compiler checks before running that you are not performing impossible operations. If you declare publicationYear as an integer and try to store the text "unknown" in it, the program never even compiles. This has a cost (you write more) and a huge advantage: an entire family of errors is caught on your machine, in seconds, instead of in production at three in the morning.
Automatic memory management
When you create objects, Java allocates memory for you in an area called the heap. When they are no longer reachable, a background process called the garbage collector frees that memory. You never write free() or delete. This eliminates the most common leaks and the use-after-free accesses, although it does not excuse you from thinking: keeping references to millions of objects in a list you never clear is still a leak, just a different kind.
Portability
We have already seen it: it is the consequence of bytecode and the JVM. Its practical value is that you can develop on a Windows or macOS laptop and deploy to a Linux server with reasonable confidence that the behaviour will be the same.
Robustness
Java performs many runtime checks that other languages skip: out-of-range accesses are detected, invalid type conversions are detected, and errors are reported through exceptions, a structured mechanism for propagating and handling failures (you will study it in depth in module 6). The effect is that a Java program that fails usually does so loudly and traceably, with a stack trace that says exactly which line it happened on.
Built-in concurrency
Java built threads of execution into the language itself from version 1.0, something quite unusual at the time. A Java program can serve thousands of simultaneous requests, and the standard library ships with queues, thread pools and thread-safe structures for that purpose. It is one of the reasons for its dominance on servers. You will work on it in module 8, when BiblioTech has to send reminders in the background without blocking the user.
- A brief history and the LTS release calendar
Java was released in 1995 under the Sun Microsystems umbrella. Oracle acquired Sun in 2010 and has maintained the language ever since, alongside a broad community (the OpenJDK project, which is the open-source reference implementation).
The milestones that affect you most as a developer:
| Version | Year | What it brought (summary) |
|---|---|---|
| Java 5 | 2004 | Generics, enum, autoboxing, the for-each loop |
| Java 8 | 2014 | Lambdas, Streams, Optional, the new java.time date API |
| Java 11 | 2018 | Modern HTTP client, var in lambdas, running source files directly |
| Java 17 | 2021 | Records, sealed classes, switch as an expression, pattern matching |
| Java 21 | 2023 | Virtual threads, record patterns, switch with patterns |
What LTS means and how to choose
Since 2018 Java has shipped a new version every six months (March and September). Most are feature releases, supported only until the next one comes out. Every two or three years one of them is designated LTS (Long-Term Support): it receives security updates and fixes for years.
The current LTS versions are 8, 11, 17 and 21 (plus 25, released in 2025). The practical implications:
- Production almost always runs LTS versions. No company wants to upgrade the foundation of its platform every six months.
- Java 17 is today the reasonable minimum for a new project, and Java 21 is the most common choice when there are no constraints. This course uses Java 17 as its reference and explicitly flags anything that requires a higher version.
- Java 8 is still alive in an enormous amount of legacy enterprise code. If you join a company with an old codebase, you are quite likely to run into it. Everything you learn here still applies; some modern conveniences simply will not be available.
- Where Java is used today
It is worth knowing what doors what you are learning opens:
- Enterprise backend. This is its dominant territory. Banks, insurers, telecoms, public administrations and e-commerce run their core services on Java, usually with Spring Boot (module 11). The systems that move money and cannot go down tend to be written in Java.
- Android. For years, Android development was pure Java. Today Kotlin is the recommended language, but Kotlin runs on the same virtual machine, interoperates with Java and shares its libraries. Knowing Java is still a direct foundation for mobile development.
- Big data and distributed processing. Hadoop, Spark, Kafka, Elasticsearch, Flink: modern data infrastructure is mostly written in Java or Scala on the JVM.
- Tools and systems. IDEs such as IntelliJ IDEA and Eclipse, integration servers such as Jenkins, databases such as Cassandra and Neo4j.
- Embedded systems and smart cards, a less visible but real niche.
- The course project: BiblioTech
Learning to program by reading examples that have nothing to do with each other does not work. That is why this course builds a single real system, incrementally, from the first lesson to the last.
The scenario
Nexus Software is a development company with around two hundred people. It has an internal technical library: several hundred books on programming, architecture and management that employees borrow. Until now it was managed with a shared spreadsheet, with the predictable problems: nobody knows who has what, books disappear and there is no way to tell how long each copy has been on loan.
Your assignment is to build BiblioTech, the system that will replace that spreadsheet.
The data you will work with throughout the course will always be the same, so that you can focus on the new concept rather than on understanding the example:
| Element | Recurring values |
|---|---|
| Company | Nexus Software |
| Employees | Marta Ruiz, Diego Alonso, Nuria Vidal |
| Books | "Effective Java" (ISBN 978-0000000001), "Design Patterns" (ISBN 978-0000000002), "Refactoring" (ISBN 978-0000000003) |
| Main class | BiblioTechApp |
How BiblioTech grows over the course
flowchart LR
M1["Module 1<br/>A linear program<br/>that calculates a fine"] --> M2["Modules 2-3<br/>Interactive menu<br/>and Book/Employee classes"]
M2 --> M3["Modules 4-5<br/>Catalog with<br/>collections"]
M3 --> M4["Modules 6-7<br/>Controlled errors<br/>and CSV import"]
M4 --> M5["Modules 8-9<br/>Background reminders<br/>and remote lookup"]
M5 --> M6["Modules 10-12<br/>Streams, Spring,<br/>database and web"]
By the end of the course you will have built, step by step and understanding every decision, an application with a book catalog, loan and reservation management, fine calculation, data import and export, background tasks, remote access, automated tests and a deployed web interface. It will not be a toy: it will be a project you can show people.
Where you are now
In this module 1 you will write the first version of BiblioTechApp: a linear program, with no repetition or complex decisions, that asks for the details of a loan on the console and prints a receipt with the calculated fine. All of it inside a single main method, using variables, operators and console input/output. It is deliberately limited, and in lesson 01-07 we will analyse exactly what it lacks and which module solves each gap.
Common Mistakes and Tips
- Confusing the Java language with JavaScript. They have no technical relationship whatsoever beyond the name, which was a marketing decision back in the nineties. Syntax, execution and ecosystem are all different.
- Installing a JRE instead of a JDK. This is the classic "why doesn't
javacwork?". Without a JDK you have no compiler. We will fix that in the next lesson. - Believing that WORA means "it works on any version". Bytecode is portable across operating systems, not across JVM versions going backwards. Compiling with JDK 21 and running on a JVM 17 produces the
UnsupportedClassVersionErrorerror. - Picking the latest version without thinking. For learning, any recent LTS will do. For a real project, first check which version your framework, your server and your cloud provider support.
- A tip on method: type every example in the course by hand, without copying and pasting. The compilation errors you will make while doing so are an essential part of learning, and learning to read them (lesson 01-03) will save you hundreds of hours.
- A tip on resources: get into the habit from day one of consulting the official Java API documentation. It is dense at first, but it is the source of truth and every Java developer uses it daily.
Exercises
Exercise 1: The journey of the code
Explain in your own words, without looking at the text, what happens from the moment you save a BiblioTechApp.java file until you see the result on screen. Mention the names of the intermediate files and the tools involved. Then answer: if you send only the .class file to a colleague who uses Linux while you use Windows, will they be able to run it? And what if you compiled with JDK 21 and they have a JVM 17 installed?
Exercise 2: Deciding the version for Nexus Software
Nexus Software is about to start BiblioTech as a new project. The systems team maintains another application running on Java 8 and asks whether BiblioTech should use the same version "to keep things simple". Write a reasoned recommendation of three or four points: which version you would choose, what arguments you would give, and what the real risk is in each option.
Exercise 3: Researching the ecosystem
Find three applications or platforms you use (or have heard of) and find out whether they are built entirely or partly on the JVM. For each one, note which part of the system uses Java and why you think that language was chosen over another.
Solutions
Solution 1
The journey has three stages:
- Editing.
BiblioTechApp.javais plain text. It is not executable; no machine understands it directly. - Compilation. The
javactool, included in the JDK, reads the.javafile, checks that the syntax and the types are correct and generatesBiblioTechApp.classcontaining bytecode. If there is a type or syntax error, this step fails and nothing is generated. - Execution. The
javacommand starts a JVM, which loads the.classfile, verifies the bytecode and begins running it. The JIT compiler translates the most frequently executed parts into native instructions, and the garbage collector manages memory in parallel.
On the two questions:
- Windows → Linux: yes, it works. That is exactly the purpose of WORA. The
.classfile contains neither x86 nor ARM instructions, but bytecode; the Linux JVM translates it into whatever that machine needs. - JDK 21 → JVM 17: it does not work. The
.classfile has a format version number recorded inside it. A JVM 17 refuses to load a.classgenerated for 21 and throwsUnsupportedClassVersionError. Java compatibility is forward (a newer JVM runs older classes), not backward. If you need to compile with a modern JDK but run on an older JVM, there is thejavac --release 17option, which generates bytecode compatible with that version.
Solution 2
A defensible recommendation would be:
- I would choose Java 21 (or, failing that, Java 17). Both are LTS, with guaranteed support and security updates for years, and they are the versions that today's ecosystem frameworks expect.
- The productivity argument. Java 17 and 21 bring features that cut boilerplate and errors: records for modelling data,
switchas an expression, pattern matching, text blocks. In a project like BiblioTech, which is going to model books, employees and loans, this shows from day one. - The ecosystem compatibility argument. Current versions of Spring Boot require Java 17 as a minimum. Starting on Java 8 would shut the door on the supported versions of the framework we will use in module 11.
- The real risk of each option. Choosing Java 21 does not force anyone to touch the existing application: two applications can coexist on the same server with different JVMs, and today it is common for each service to bundle its own (in a container, for example). The real risk is in the opposite choice: starting a new project in 2026 on Java 8 means being born with technical debt, on a version whose support is paid or limited and which many modern libraries no longer accept.
Conclusion of the recommendation: the simplification the systems team is proposing is only apparent; the cost of maintaining an obsolete version in a new project far outweighs the cost of managing two versions.
Solution 3
There is no single correct answer, but a good answer should identify patterns like these:
- A mobile banking application. The backend (accounts, transfers, fraud detection) is usually Java with Spring. Reasons: maturity, transactional support, availability of professional profiles and decades of code proven in the financial sector.
- An Android application. The app runs on ART, a virtual machine that executes bytecode derived from Java's. Even though it is written in Kotlin today, the whole execution model and much of the API are a direct inheritance from Java.
- An internal search engine or an analytics platform. Elasticsearch is written in Java; so are Kafka and Spark. Reason: the JVM offers very high performance with automatic memory management, excellent concurrency support and portability across the thousands of servers in a cluster.
What matters in this exercise is not getting the facts right, but spotting the pattern: Java dominates where long-term reliability, concurrency and maintenance by large teams matter, rather than where what matters is writing the prototype in two afternoons.
Conclusion
You now have the map. Java is both a language and a platform; its portability comes from compiling to bytecode and running it on a JVM specific to each system; the JDK is what you will install because it contains the compiler, the JRE and the JVM; and the LTS versions (8, 11, 17, 21) set the industry's real pace, with Java 17 as this course's reference. You also know that Java lives above all in the enterprise backend, on Android and in data infrastructure, and you have met the BiblioTech project you will shape module by module for Nexus Software.
With the theory in place, it is time to prepare the ground. In the next lesson, Setting Up the Development Environment, you will install a JDK on your system, check that java and javac respond, understand what JAVA_HOME and PATH are for, compile and run your first file from the terminal, meet JShell and choose the IDE you will work with for the rest of the course.
Java Programming Course
Module 1: Introduction to Java
- Introduction to Java
- Setting Up the Development Environment
- Basic Syntax and Structure
- Variables and Data Types
- Operators
- Console Input and Output
- Your First Complete Program: BiblioTech
Module 2: Control Flow
- Conditional Statements
- Loops
- Switch Statements
- Break and Continue
- Debugging and Execution Traces
- Project: The BiblioTech Interactive Menu
Module 3: Object-Oriented Programming
- Introduction to OOP
- Classes and Objects
- Methods
- Constructors
- Inheritance
- Polymorphism
- Encapsulation
- Abstraction
- The Object Class: equals, hashCode and toString
Module 4: Advanced Object-Oriented Programming
- Interfaces
- Abstract Classes
- Inner Classes
- Anonymous Classes
- Lambda Expressions
- Functional Interfaces and Method References
- Enums and Records
Module 5: Data Structures and Collections
- Arrays
- The Collections Framework
- ArrayList
- LinkedList
- HashMap
- HashSet
- Queue and Deque
- Stack
- Sorting and Searching Collections
Module 6: Exception Handling
- Introduction to Exceptions
- The Try-Catch Block
- Throw and Throws
- Custom Exceptions
- The Finally Block
- Try-with-resources and AutoCloseable
- Error Handling Strategies and Logging
Module 7: File Input/Output
- Reading Files
- Writing Files
- File Streams
- BufferedReader and BufferedWriter
- Serialization
- The NIO.2 API: Path and Files
- Interchange Formats: CSV and Properties
Module 8: Multithreading and Concurrency
- Introduction to Multithreading
- Creating Threads
- Thread Lifecycle
- Synchronization
- Concurrency Utilities
- Concurrent Collections and Atomic Variables
- Asynchronous Tasks with CompletableFuture
Module 9: Networking
- Introduction to Networking
- Sockets
- ServerSocket
- DatagramSocket and DatagramPacket
- URL and HttpURLConnection
- The Modern HTTP Client
Module 10: Advanced Topics
- Generics
- Annotations
- Reflection
- Java 8 Features: Streams and Optional
- Dates and Times with java.time
- Java 9 and Beyond
- Memory, Garbage Collection and Performance
Module 11: Java Frameworks and Libraries
- Introduction to Java Frameworks
- Spring Framework
- Hibernate
- JUnit
- Maven
- Advanced Testing with Mockito
- Essential Ecosystem Libraries
