Learnitweb

How the JVM Runs Your Code

What exactly does the JVM do when it runs our code?

Most developers know that Java is a compiled language—yet not compiled in the same sense as C or C++.
Instead, Java follows a unique two-step model:

  1. Compile Java source code → Bytecode
  2. Run that bytecode on the Java Virtual Machine (JVM)

Understanding this lifecycle is essential because every optimization, performance decision, and runtime behavior in Java flows from this model.

Let’s break it down.

1. From Java Code to Bytecode

When you write Java code:

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello JVM");
    }
}

the Java compiler (javac) transforms this .java file into a .class file.

What is inside a .class file?

  • Bytecode: A set of low-level, platform-independent instructions.
  • Metadata: Method definitions, constant pool, variable info, etc.

These .class files may later be grouped into:

  • JARs (Java ARchive)
  • WARs (Web Application Resource)
  • EARs (Enterprise Archive)

2. “Write Once, Run Anywhere”: Why Bytecode Matters

One of Java’s biggest promises—especially when it was created in the 1990s—was:

Write code once, run it anywhere.

This is made possible by bytecode + JVM:

  • Your program compiles into bytecode.
  • Any machine with a JVM—Windows, macOS, Linux—can execute that bytecode.
  • The underlying hardware no longer matters.

Your Java program works the same across all supported platforms because:

The JVM abstracts away the machine-specific details.

3. JVM Does NOT Simply “Interpret” Bytecode

Many beginners believe:

“Java code → compiled to bytecode → JVM interprets the bytecode.”

This is only partially true.

If the JVM were only an interpreter:

  • Performance would be slow.
  • Every instruction would be analyzed repeatedly at runtime.
  • Programs would behave like purely interpreted languages (e.g., older PHP versions or Python CPython).

But the JVM is far more advanced

The JVM includes:

  • JIT (Just-In-Time) Compiler
  • Adaptive optimization
  • Hotspot detection
  • Inline caching
  • Escape analysis
  • Garbage collection algorithms
  • Thread & memory management capabilities

This means:

The JVM dynamically optimizes your code based on how it is actually used at runtime.

This adaptive nature is one of the reasons Java often outperforms purely interpreted languages.

4. JVM Can Run Any Language That Compiles to Bytecode

Although Java was the original language for the JVM, it’s no longer alone.

Any language that can generate JVM-compatible bytecode can run on the JVM.

This includes:

  • Kotlin
  • Scala
  • Groovy
  • Clojure
  • JRuby
  • Jython
  • Frege (Haskell for JVM)
  • And many more

This makes the JVM not just a runtime for Java, but a powerful execution platform for many modern languages.

Everything we learn about:

  • memory management
  • class loading
  • bytecode execution
  • performance optimizations

will apply to all these JVM languages as well.

5. A Preview of What’s Ahead

Later in the course, especially in the final chapter, we will:

  • Inspect real Java bytecode
  • Compare Java-generated bytecode with bytecode from a different JVM language
  • Understand how language features translate into bytecode instructions

This will help you develop a deeper sense of:

  • how the JVM sees your program
  • why certain code patterns perform better
  • how tooling like profilers and debuggers understand your application

But for now, our focus is simpler:

6. What Happens When the JVM Runs Bytecode?

When you execute:

java MyApplication

the following occurs:

  1. JVM loads your bytecode
  2. ClassLoader locates and brings required classes into memory
  3. Bytecode verifier ensures safety
  4. JIT compiler selectively compiles hot code paths
  5. Interpreter executes cold or rarely used code
  6. Garbage collector manages memory
  7. Runtime environment manages threads, stack frames, and method calls

Understanding these steps will help you become a more advanced Java developer and will clarify:

  • performance bottlenecks
  • memory usage issues
  • JVM tuning
  • how modern frameworks behave internally