1.2
JVM, JRE, JDK, and Your First Program
Install the tools, compile one Java file, and run it from the terminal.
Before you start
Topics used in this lesson
Prerequisites
Section 1.1 established the route from source code to a platform:
source -> bytecode -> JVM -> processor and operating systemThis lesson makes that route concrete. You will create one file, compile it, inspect the result, and run it without an IDE.
Why this matters
Java installation instructions use three similar names: JVM, JRE, and JDK. Mixing them up creates practical confusion.
Someone installs a runtime and expects to find a compiler. Another person passes a .class file to javac. An IDE hides both mistakes until a terminal or server exposes them.
We need one accurate model, then one complete trip through the tools.
Core explanation
The three names
- javac compiler
- java launcher
- inspection and debugging tools
- runtime modules
Install this when you develop Java programs.
- JVM
- standard runtime libraries
- supporting runtime files
The traditional package for running Java applications.
- class loading
- bytecode execution
- managed memory
The engine defined by the JVM specification and implemented by a runtime.
The conceptual nesting is still useful. Modern JDKs may not ship a separate folder or download named JRE.
Use these working definitions:
- The JVM executes class files under the JVM rules.
- A runtime environment adds the libraries and files applications need.
- The JDK adds tools used to build, inspect, and debug programs.
For this course, install a JDK. It contains what you need for both development and execution.
Install one
Get a build of OpenJDK version 21. It is a long-term support release, and every command in this course works on it. Version 17 also works if you already have it. Anything older is missing language features used later in the course.
Adoptium publishes free, well-maintained builds for all three operating systems. Download the installer for your machine, not a .zip or .tar.gz, and choose the package marked JDK. A package marked JRE gives you java without javac.
macOS
- Pick the right fileChoose the
.pkginstaller. Select aarch64 for Apple Silicon (M1 and later) or x64 for an Intel Mac. The Apple menu, then About This Mac, names your chip. - Run the installerOpen the
.pkgand accept the defaults. It installs the JDK and putsjavaandjavacon yourPATHfor you. - Open a new terminalOpen Terminal from Applications, then Utilities. A terminal that was already open will not see the new installation.
Windows
- Pick the right fileChoose the
.msiinstaller for x64. - Turn on the PATH optionsThe installer shows a screen of optional features. Set Add to PATH and Set JAVA_HOME variable to "Will be installed on local hard drive". This is the step that decides whether the next section works.
- Open a new terminalPress Start, type
powershell, and open Windows PowerShell. A window that was already open still has the oldPATH.
Linux
- Install from your package managerOn Debian or Ubuntu:
sudo apt updatethensudo apt install openjdk-21-jdk. On Fedora:sudo dnf install java-21-openjdk-devel. - Install the right packageThe name matters.
openjdk-21-jreand packages ending in-headlessdo not includejavac.
Confirm the installation
Open a terminal and run:
java -version
javac -versionThe first command checks the launcher. The second checks the compiler.
If java works but javac does not, you may have only a runtime on your command path. If neither works, the JDK may be missing or its bin directory may not be on PATH.
PATH is the list of directories your shell searches for commands. It is an operating-system feature, not a Java keyword.
Write a complete program
Create a plain text file named Demo.java:
public class Demo {
public static void main(String[] args) {
System.out.println("Hello, Java!");
}
}Every part has a job:
public class Demo declares a class named Demo
public static void main(...) declares the program entry method
String[] args receives command-line arguments
System.out.println(...) prints one lineYou do not need the full meaning of public, static, or String[] yet. Their later lessons will rebuild this line from known parts.
One rule matters now: a public top-level class named Demo belongs in Demo.java. Capitalisation must match.
Compile it
Change the terminal to the directory containing the file. Run:
javac Demo.javaIf compilation succeeds, the command usually prints nothing. It creates Demo.class in the same directory.
You now have two different artifacts:
| Demo.java | Demo.class | |
|---|---|---|
| Contains | Java source text | Class-file data and bytecode |
| Made for | Humans and javac | A compatible JVM |
| Typical action | Edit and compile | Load and execute |
Run it
Run the class through the Java launcher:
java DemoExpected output:
Hello, Java!javac accepts a file name, including .java. The java launcher accepts a binary class name, so you write Demo without an extension.
Optional internals
Going deeperOpen optional internalsYou can finish the core lesson without this section.
Compile-time errors and run-time errors are different
Remove the semicolon after println, then run javac Demo.java. The compiler reports a source error and does not produce a new valid class file.
Restore the semicolon, compile, then run java Missing. The launcher cannot find a class with that name.
These failures occur at different stages:
Find the failing stage
- Source parsing and type checkingjavac reports invalid Java source.
- Class lookupThe launcher reports that the requested class cannot be found.
- Entry-point lookupThe class exists, but no suitable main method exists.
- Program executionThe program starts and may then throw an exception.
Reading the stage is faster than treating every red message as the same problem.
The class path answers “where?”
By default, java Demo searches the current directory for Demo.class. That search location is part of the class path.
You can state the current directory explicitly:
java -cp . Demo-cp means class path. The dot means the current directory.
Packages later add directory structure and qualified names. The same lookup rule remains: the runtime needs both the class name and a place to search.
What the runtime does with the class
Before your first println executes, the runtime performs several jobs.
- Loading: locate the bytes for
Demoand create the JVM’s in-memory representation. - Verification: check structural and bytecode safety rules.
- Linking: prepare class data and resolve required symbolic references.
- Initialization: run required static initialization for the class.
- Invocation: call the valid
mainmethod.
That is why java Demo does more than open a file and read instructions from the first byte.
Interpreting and compiling at run time
javac is an ahead-of-time compiler from Java source to JVM bytecode. That makes Java a compiled language.
A common JVM can also interpret bytecode and compile selected methods into native code while the program runs. The second compiler is called a just-in-time compiler, or JIT compiler.
Runtime profiling lets the JVM spend optimisation effort where the program actually spends time. Code that rarely runs may not need expensive compilation.
These are implementation strategies. The JVM specification defines observable behaviour, not one mandatory balance between interpretation and JIT compilation.
You can inspect the class file without decoding raw bytes:
javap -c Demojavap is a JDK tool. The -c option prints readable bytecode instructions for each method.
SE, EE, and ME describe platforms and ecosystems
Java SE is the standard Java platform and core API used throughout this course.
Jakarta EE, historically called Java EE, adds specifications for enterprise server applications. It builds on Java SE rather than replacing it.
Java ME targets constrained and embedded environments. Its role is much smaller in modern general-purpose Java development.
These labels are not three different Java languages. They describe platform profiles, APIs, and deployment environments around the language.
Tradeoffs
An IDE can compile and launch Java for you. That is useful after you understand the two commands it is running.
Learning the terminal route exposes file names, class names, stale class files, and class-path mistakes. Those details return in build tools, test runners, servers, and production diagnostics.
The small cost now prevents the development environment from becoming a black box.
Check yourself
Answer from memory before opening the explanation. Then compare your rule with the answer and revisit the example if they differ.
You want to write, compile, and run Java programs. Which package do you install?
Show the answer
Install a JDK. It provides the Java runtime, the
javaccompiler, and development tools. A JVM is the execution engine. JRE is the traditional name for a JVM plus runtime libraries and supporting files.Why does compilation use "javac Demo.java", while execution uses "java Demo"?
Show the answer
javaccompiles a source file, so it receives the file path. The launcher receives a binary class name. It searches the class path forDemo.class, loads that class, and calls its entry method.What happens before the first statement in main runs?
Show the answer
The launcher starts a JVM. The runtime locates and loads the class, checks its bytecode, links it, and initializes required class state. It then invokes a valid
mainmethod.
Exercises
Start with the warm-ups. Continue to practice exercises when the basic idea works. Challenges are optional: skip them on a first pass and return after the next lesson.
- Warm up: one idea with close guidance.
- Practice: combine the idea with earlier material.
- Challenge: investigate an edge case or implementation detail.
4 exercises60 pointsabout 36 minutes
Verify a JDK Installation
ex-1-2-aInstalling a package and having a working command-line toolchain are different outcomes. Select the observations that prove both the runtime and compiler are ready.
Your First Program, the Slow Way
ex-1-2-bWrite, compile and run a Java program using nothing but a text editor and a terminal.
Do not use the Run button in VS Code or IntelliJ for this one. Use it for the rest of your life if you want, but do this one by hand.
The reason is simple. That green button runs javac and then java for you and hides both. If you have never seen the two steps separately, then compiling and running are one mysterious action in your head, and every error message from either one will look the same to you.
Do it once by hand and they become two clearly different things forever.
Steps and success checks
- Save the file as Demo.java, with a capital D
- Compile it from the terminal, not with a Run button
- Confirm that Demo.class appeared next to Demo.java
- Run it from the terminal and see the output
public class Demo {
public static void main(String[] args) {
System.out.println("Hello from bytecode");
}
}
Sample run
javac Demo.java
java Demo
Hello from bytecode
Hint 1
cd. On Windows, Command Prompt uses cd too.Hint 2
javac Demo.java nothing is printed. That is success. A compiler that has nothing to complain about says nothing. Check with ls or dir that Demo.class exists.Hint 3almost the answer
java Demo. Not java Demo.java, and not java Demo.class. The java command wants a class name, and it finds the file itself.Read Bytecode Output
ex-1-2-cThe disassembler shows instructions such as ldc and invokevirtual, plus a constructor block. Select every conclusion supported by those details.
Identify the Failing Tool
ex-1-2-dTwo failures happen while compiling source code. Two happen only when the program is launched. Choose the row that puts each failure on the correct side.
Where this leads
You have completed the first full Java toolchain cycle:
Demo.java -> javac -> Demo.class -> java -> class loading -> mainThe next phase begins with the values that move through those bytecode instructions.
Later connections
- BytecodeOverloading is decided here, at compile time, not while running.5.1 - Methods, Calls, Recursion, and Overloading
- BytecodeOverriding is the opposite: bytecode leaves the choice for later.7.2 - Abstraction, Polymorphism, Abstract Classes, and Interfaces
- BytecodeThe Method Area is where this bytecode lives while your program runs.Phase XIII. Memory and the Garbage Collector
- JVMHeaders, field layout, references, and alignment depend on the JVM configuration.6.3 - Objects in Memory: Size, Copying, Passing
- JVMA full tour of every memory area the JVM keeps.Phase XIII. Memory and the Garbage Collector
- JVMThreads are the JVM handing work to your CPU cores.Phase XIV. Concurrency
JVM is next used in 4.2 - How Arrays Work