Java Introduction: JVM, Compilation, and Hello World
2297 words
11 min read
Visual companion
Python
Type and operator map
Python Week 1: the first filter for runtime behavior
View
Revision summary
What this note is really saying
Short form
# Java Introduction: JVM, Compilation, and Hello World ## 🎯 Learning Objectives By the end of this topic, you will be able to: - Explain how Java achieves platform independence via the JVM - Trace the full compilation and execution pipeline of a Java program - Write, compile, and run a basic Java program from the c...

Java Introduction: JVM, Compilation, and Hello World
🎯 Learning Objectives
By the end of this topic, you will be able to:
- Explain how Java achieves platform independence via the JVM
- Trace the full compilation and execution pipeline of a Java program
- Write, compile, and run a basic Java program from the command line
- Understand the structure of the
mainmethod and its role - Distinguish between JDK, JRE, and JVM components
📋 Prerequisites
- BSCS1002 — Python Programming: You already know what a programming language is and have written at least one "Hello World" program. Java differs in being compiled (not interpreted) and statically typed (types checked at compile-time, not runtime).
- BSCS1001 — Computational Thinking: Familiarity with what a program, algorithm, and computer execution mean.
1. The "Why" — What Problem Does Java Solve?
1.1 Intuition: Write Once, Run Anywhere
Imagine you write a letter in English and want it read in three countries — India, Japan, and Germany. In each country, you could hire a translator who reads the English letter and speaks it aloud in the local language. The letter (your code) stays the same; only the translator (the JVM) changes per country (operating system).
This was Java's revolutionary idea in 1995: Write Once, Run Anywhere (WORA). Unlike C/C++ where you compile separately for Windows, macOS, and Linux, Java compiles to an intermediate form — bytecode — that runs on any machine that has a Java Virtual Machine (JVM) installed.
1.2 The Problem Java Solves
Before Java, developers had to:
- Compile separate executables for each platform
- Test on every OS
- Deal with platform-specific bugs (memory layouts, OS APIs) Java removed this by inserting a virtual machine layer between your program and the hardware.
1.3 Mental Model: The Compilation Pipeline
javaYourCode.java (source) │ ▼ javac (compiler) YourCode.class (bytecode) │ ▼ java (launcher → JVM) JVM interprets/compiles bytecode to machine code │ ▼ OS / Hardware
The
.class file with bytecode is portable — copy it to any machine with a JVM and it runs.2. The Compilation & Execution Pipeline
2.1 Step-by-Step Breakdown
| Step | Tool | Input → Output | What Happens |
|---|---|---|---|
| 1. Write | Any text editor | Hello.java (source) | You write human-readable code |
| 2. Compile | javac | Hello.java → Hello.class | javac checks syntax and types, emits bytecode |
| 3. Load | java (class loader) | Hello.class → JVM memory | JVM reads the .class file into memory |
| 4. Verify | Bytecode verifier | Bytecode → verified bytecode | JVM checks bytecode safety (no illegal operations) |
| 5. Execute | JIT compiler / Interpreter | Bytecode → machine instructions | JVM translates bytecode to native CPU instructions |
| 6. Output | System | Console output | Your program prints results |
2.2 Why is Bytecode Safe?
The bytecode verifier ensures:
- No stack overflow/underflow
- All instructions operate on correct types
- No illegal memory access (unlike C pointers)
- Access to private members is prevented This is why Java is considered memory-safe — it prevents whole categories of bugs that plague C/C++.
2.3 Mental Model: JIT Compilation
Early JVMs were pure interpreters (slow). Modern JVMs use a Just-In-Time (JIT) compiler:
pseudoHot method detected (runs frequently) │ ▼ JIT compiler translates bytecode → native machine code │ ▼ Native code cached and reused (much faster)
The JVM starts interpreting, profiles which methods are "hot" (executed frequently), then compiles only those to native code. This gives Java near-native speed for performance-critical paths.
3. Your First Java Program
3.1 Syntax and Structure
java// Hello.java — Every Java program starts here public class Hello { // Class declaration: public class ClassName public static void main(String[] args) { // Entry point System.out.println("Hello, World!"); // Print to console } }
3.2 File Naming Rule — CRITICAL
In Java, the public class name must match the filename. So
Hello.java must contain public class Hello. If you name the file Goodbye.java with public class Hello, the compiler throws an error.Why this matters: The JVM looks for a.classfile named after the class. If the file isHello.classbut the source wasGoodbye.java, the compiler can't find the right file.
3.3 The main Method — Deconstructed
javapublic // Anyone can call it (the JVM is "anyone") static // No object needed — JVM invokes it before any objects exist void // Returns nothing main // Fixed name — the JVM looks for exactly "main" (String[] args) // Command-line arguments as an array of Strings
3.4 Compiling and Running
bash# 1. Write the code in Hello.java # 2. Compile to bytecode javac Hello.java # Produces: Hello.class # 3. Run (note: no .class extension!) java Hello # Output: Hello, World!
Common Mistake: Runningjava Hello.classinstead ofjava Hello. Thejavacommand expects a class name, not a filename.
4. JDK vs JRE vs JVM
Many beginners confuse these three. Here's the distinction:
| Component | Full Name | Contains | Used For |
|---|---|---|---|
| JDK | Java Development Kit | JRE + compiler (javac), debugger, tools | Developing Java programs |
| JRE | Java Runtime Environment | JVM + core libraries (rt.jar) | Running Java programs |
| JVM | Java Virtual Machine | Bytecode interpreter, JIT, garbage collector | Executing bytecode |
pseudo┌─────────────────────────────────────┐ │ JDK │ │ ┌───────────────────────────────┐ │ │ │ JRE │ │ │ │ ┌─────────────────────────┐ │ │ │ │ │ JVM │ │ │ │ │ │ ┌────────┐ ┌─────────┐ │ │ │ │ │ │ │JIT │ │ GC │ │ │ │ │ │ │ └────────┘ └─────────┘ │ │ │ │ │ │ ┌─────────────────────┐ │ │ │ │ │ │ │ Core Libraries │ │ │ │ │ │ │ └─────────────────────┘ │ │ │ │ │ └─────────────────────────┘ │ │ │ │ ┌─────────────────────────┐ │ │ │ │ │ javac, jar, javadoc │ │ │ │ │ └─────────────────────────┘ │ │ │ └───────────────────────────────┘ │ └─────────────────────────────────────┘
For this course: Install the JDK. When you run
javac, you're using the JDK. When you run java, you're invoking the JRE which starts the JVM.5. Java vs Python: Key Differences at a Glance
| Feature | Java | Python |
|---|---|---|
| Paradigm | Statically typed (types checked at compile time) | Dynamically typed (types checked at runtime) |
| Execution | Compiled to bytecode, then JIT'd | Interpreted (compiled to bytecode internally) |
| Speed | Fast (JIT-compiled) | Slower (interpreted) |
| Syntax verbosity | Verbose (every variable needs a type) | Concise (no type declarations needed) |
| Entry point | public static void main(String[] args) | Just top-level code (or if __name__ == "__main__") |
| Memory | Automatic garbage collection | Automatic garbage collection |
| Platform | JVM (any OS with JVM) | Python interpreter (any OS with Python) |
Example: Hello World in Both
python# Python — concise print("Hello, World!")
java// Java — more ceremony public class Hello { public static void main(String[] args) { System.out.println("Hello, World!"); } }
This is not a flaw — it's intentional. Java's verbosity ensures that every intention is explicitly declared, making large codebases more maintainable.
6. Common Pitfalls
Pitfall 1: Class Name Mismatch
Mistake: File is
hello.java but class is Hello (or vice versa).javapublic class Hello { } // File must be Hello.java, not hello.java
Why: Java is case-sensitive. On some OS (Windows), the filesystem is case-insensitive, so
hello.java compiles but fails on Linux. Fix: Always match filename exactly to the public class name, including case.Pitfall 2: main Method Signature Errors
Mistake: Wrong signature (e.g.,
public void main, static public void main, missing String[] args).javapublic class Test { public void main(String[] args) { } // Missing static! }
Error: "Main method not found in class Test" Fix: The exact signature is
public static void main(String[] args) — every keyword matters.Pitfall 3: Running with .class Extension
Mistake:
java Hello.class instead of java Hello Error: "Could not find or load main class Hello.class" Why: The java command expects a class name, not a file path. It appends .class internally and searches the classpath. Fix: Drop the extension: java Hello.Pitfall 4: Forgetting to Compile First
Mistake: Editing Hello.java and immediately running
java Hello. Error: The old .class file (if any) runs, not your new code. Fix: Always compile first: javac Hello.java then java Hello.7. Practice Questions
Q1: What does JVM stand for and what is its primary role?Answer: JVM stands for Java Virtual Machine. Its primary role is to execute Java bytecode (.classfiles) by translating it into native machine code for the underlying operating system and hardware. It provides platform independence — the same bytecode runs on any OS with a compatible JVM.The JVM also handles memory management (garbage collection), security (bytecode verification), and runtime optimization (JIT compilation). Q2: Trace the complete path from a .java file to a running program.Answer:
- Write
Hello.javasource code- Compile with
javac Hello.java→ producesHello.class(bytecode)- Load — JVM's class loader reads
Hello.classinto memory- Verify — bytecode verifier checks for illegal instructions
- Execute — JVM's execution engine (interpreter + JIT compiler) translates bytecode to native machine instructions
- Output — program's output appears on console Q3: What is the output of running these commands?
bash$ javac MyProg.java $ java MyProg.classAnswer: Thejavacommand should bejava MyProg(without.class). Runningjava MyProg.classproduces: "Could not find or load main class MyProg.class"The JVM expects a class name, not a filename. When givenMyProg.class, it looks for a class namedMyProg.class(with the dot in the name), which doesn't exist. Q4: What is the difference between JDK, JRE, and JVM?Answer:
- JDK (Java Development Kit): Full toolkit for developers — includes JRE + compiler (
javac), debugger, documentation tools- JRE (Java Runtime Environment): For running Java programs — includes JVM + core libraries
- JVM (Java Virtual Machine): The engine that executes bytecode — includes interpreter, JIT compiler, garbage collector
Relationship: JDK ⊃ JRE ⊃ JVM (the JDK contains the JRE, which contains the JVM). Q5: Why does this code fail to compile?javapublic class hello { public static void main(String[] args) { System.out.println("Hello"); } }Assume the file is namedhello.java.Answer: On most systems this would compile fine. But consider if the file is namedHello.java(capital H) and the class ishello(lowercase h). In Java, the public class name must exactly match the filename. Some compilers are case-sensitive and will rejectHello.javacontainingpublic class hello.The correct approach: either rename the class toHello(matching the filename) or rename the file tohello.java(matching the class). Q6: What is bytecode and why is it useful?Answer: Bytecode is an intermediate, platform-independent binary representation of Java code, stored in.classfiles. It is not native machine code for any specific CPU. Its usefulness:
- Platform independence: Same bytecode runs on any OS (Windows, Linux, macOS) with a JVM
- Security: Bytecode verification happens before execution, catching illegal operations
- Compact format: More compact than source code, faster to transmit over networks
- Optimization: JIT compiler can optimize frequently-executed bytecode paths Q7: Can a .java file have more than one class? If so, how many can be public?
Answer: Yes, a.javafile can contain multiple classes, but only one can bepublic, and that public class must match the filename. For example:java// File: Shape.java public class Shape { // Only this is public // ... } class Circle { // Package-private (OK) // ... } class Square { // Package-private (OK) // ... }CompilingShape.javaproduces three.classfiles:Shape.class,Circle.class,Square.class. Q8: What would happen if you remove thestatickeyword from the main method?javapublic class Test { public void main(String[] args) { System.out.println("Hello"); } }Answer: It compiles successfully (it's a valid method), but when you runjava Test, you get: Error: Main method is not static in class Test. Please define the main method as:public static void main(String[] args)The JVM callsmainwithout creating any object first — it must bestaticto exist before any instances exist. Q9: If you have a program with no main method, does it compile? Does it run?javapublic class NoMain { public void doSomething() { System.out.println("Doing something..."); } }Answer: It compiles successfully (javac checks syntax, not runtime behavior). But when you try to run it withjava NoMain, you get: Error: Main method not found in class NoMainA compiled Java program can exist without a main method (libraries, applets), but it cannot be executed as a standalone program. Q10: What is the JIT compiler and how does it improve performance?Answer: JIT (Just-In-Time) is a component of the JVM that improves performance by:
- Profiling: The JVM starts interpreting bytecode and profiles which methods are executed frequently ("hot spots")
- Compilation: Hot methods are compiled from bytecode directly to native machine code
- Caching: The compiled native code is cached and reused for subsequent calls
This gives Java near-native performance for frequently-executed code paths while maintaining portability. The longer a Java program runs, the faster it gets as more code is JIT-compiled.
🔗 Cross-References
- Next: Data Types & Operators — understanding Java's type system
- Python Comparison: See BSCS1002 Python — Introduction to Python
- Memory Model: Stack and Heap Memory — what happens when your program runs
- Reference: Oracle Java Tutorials — "Hello World!" Application Join Discord Next1.2 Data Types & Operators