# Compile Java source into bytecode (.class)
javac -d bin src/Main.java
# Execute compiled class with JVM
java -cp bin Main
# Package compiled classes into executable JAR
jar --create --file app.jar --main-class Main -C bin .
# Run packaged executable JAR
java -jar app.jar
# Disassemble bytecode to inspect low-level JVM instructions
javap -c -v bin/Main.class
⚠️ 5 Fatal Traps & Engineering Pitfalls
Trap #1: NoClassDefFoundError vs. ClassNotFoundException Confusion
ClassNotFoundException is an explicit checked exception thrown when reflective lookup fails (e.g. Class.forName()). NoClassDefFoundError is a fatal JVM LinkageError meaning the class was present during compilation but missing from the runtime classpath or failed during static field initialization.
Trap #2: Bytecode Version Incompatibility (UnsupportedClassVersionError)
Compiling on a newer JDK (e.g. Java 21 emits class format version 65.0) and attempting to run on an older JRE (e.g. Java 17, version 61.0) crashes immediately with UnsupportedClassVersionError. When compiling for backward compatibility, always supply the javac --release 17 flag.
Trap #3: Classpath Delimiter OS Mismatch (Semicolon vs. Colon)
On Windows, classpath entries in -cp are separated by semicolons (bin;lib/core.jar). On Linux and macOS, they are separated by colons (bin:lib/core.jar). Hardcoding classpath strings in shell scripts without OS detection causes silent startup failures.
Trap #4: Executing Java with .class File Extension
Beginners frequently type java Main.class in the terminal, causing the JVM to search for a class named Main/class and failing with Could not find or load main class. The java command requires the fully-qualified class identifier without any extension: java Main.
Trap #5: Naive Micro-Benchmarking Without JIT Warmup
Measuring Java loop execution with System.nanoTime() over 10 iterations produces misleading results. The HotSpot JVM starts in bytecode interpreted mode, profiles execution, and triggers tiered Just-In-Time (C1/C2 JIT) native machine compilation only after thousands of invocations.
💬 Frequently Asked Questions
What is the difference between JDK, JRE, and the JVM?
The JVM (Java Virtual Machine) executes bytecode on the host OS. The JRE (Java Runtime Environment) bundles the JVM with core standard class libraries. The JDK (Java Development Kit) includes the JRE plus developer tools like javac, jar, jdb, and javap.
How does the HotSpot Just-In-Time (JIT) compiler improve execution speed?
HotSpot monitors code execution in real-time. Methods identified as "hot spots" (frequently called loops) are dynamically compiled directly into native x86_64 or ARM64 assembly instructions with aggressive optimizations like inlining, loop unrolling, and escape analysis.
What is Java bytecode and why does it enable cross-platform portability?
Bytecode is an intermediate, architecture-neutral instruction set (.class files). Instead of compiling directly to Intel or Apple Silicon machine code, javac compiles to bytecode, and the platform-specific JVM translates that bytecode to local CPU instructions.
What causes the "Could not find or load main class" error when running Java?
This occurs if the class file is not in the directory specified by -cp (classpath), if the package declaration does not match the folder structure, or if the user appended the .class extension to the command.
What is the purpose of the javap disassembly tool?
javap disassembles compiled .class files into human-readable bytecode instructions (such as iload, invokevirtual, bipush), allowing developers to inspect compiler optimizations and verify method signatures.