β˜• From Source to Runtime: How Java Code is Compiled and Executed (JVM Internals for Intermediate Developers)

Arsh GhaiwatArsh Ghaiwat
6 min read

If you're writing Java code regularly β€” whether it's for backend services, web applications, or system tools β€” understanding how your code gets executed isn't just β€œnice to know.” It's essential.

This blog will walk you through:

  • How Java code flows from .java to execution

  • What the JVM really does behind the scenes

  • Key memory areas: Stack, Heap, and Method Area

  • How static members are stored and used

  • Why Java is platform-independent

  • How input flows into your main method

  • Clarifying misconceptions around static, heap, and object-orientation

Let’s dive deep.


πŸ” Java Program Lifecycle: From Code to Output

Let’s consider a simple example:

public class Demo {
    public static void main(String[] args) {
        int a = 10, b = 20;
        int sum = a + b;
        System.out.println("Sum = " + sum);
    }
}

When you compile and run this code:

javac Demo.java
java Demo

Here’s what happens:

[.java file]
   ↓ Compilation (javac)
[.class file β†’ Bytecode]
   ↓ Execution (java)
[JVM loads β†’ verifies β†’ allocates memory β†’ executes]
   ↓
[Output: Sum = 30]

🧠 What Is the JVM?

The Java Virtual Machine (JVM) is a software-based engine responsible for:

  • Loading and executing your bytecode

  • Managing memory (stack, heap, method area)

  • Performing garbage collection

  • Converting bytecode into native code

Here’s something important:

JVM doesn’t interact with hardware initially. It compiles, validates, and stores the state of your program first β€” like static methods, static variables, class structure β€” and only when it’s time to run, it interacts with the actual machine.

The JVM is always in control of:

  • The state of your program

  • Its own stack for bytecode execution

  • Static content loaded directly into the method area

This ability to store program state is what gives the JVM flexibility, efficiency, and portability.


🧰 JDK, JRE, and JVM: How They Work Together

ComponentDescription
JDKFull development toolkit (compiler, tools, JRE)
JREJVM + libraries (used for running code)
JVMExecutes your bytecode (heart of the platform)

πŸ— JVM Architecture Overview

Here’s what the JVM consists of:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚       Class Loader         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   Runtime Memory Areas     β”‚
β”‚  (Heap, Stack, Method Area)β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚     Execution Engine       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Native Method Interface    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Let’s break these areas down.


🧠 JVM Memory Breakdown

1. πŸ”Έ Method Area (MetaSpace in Java 8+)

The Method Area is where JVM stores class-level metadata:

  • Class name, hierarchy

  • Method bytecode

  • Static variables

  • Constant pool (literals, symbols)

When the JVM starts, it directly loads static members into the Method Area. This happens before any object is created.

That’s why:

public static void main(String[] args)

...is accessible without creating an object. It's preloaded!

πŸ’‘ This also explains why you get errors like NoSuchMethodError: main if your main() is not marked static.
JVM is not concerned about your class object β€” it just looks for a static main() to begin execution.

πŸ“Œ Key Concept:

Whenever memory is allocated to a class, we call it an object. But static members are not part of object memory β€” they’re part of class-level memory (Method Area).


2. πŸ”Έ Heap

All objects (created via new) live in the Heap. It is shared across all threads and cleaned automatically using Garbage Collection.

List<String> list = new ArrayList<>();

Here, the ArrayList object is created in the heap. And remember:

βœ… Thumb Rule: Whenever you use new, memory is allocated in the heap.


3. πŸ”Έ Stack

Each thread has its own stack memory. It stores:

  • Method call frames

  • Local variables

  • References to heap objects

public class StackDemo {
    public static void main(String[] args) {
        int num = 10;             // Stored in stack
        Student s = new Student(); // Object in heap, reference in stack
    }
}

πŸ“Š Memory Layout Example

Thread-1 Stack         Thread-2 Stack
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Method A   β”‚         β”‚ Method X   β”‚
β”‚ Method B   β”‚         β”‚ Method Y   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

                Shared Heap
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚ new Student()      β”‚
          β”‚ new Book()         β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

                Shared Method Area
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚ static int count = 0;  β”‚
          β”‚ bytecode of methods    β”‚
          β”‚ constant pool          β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ” Deep Dive into static: JVM, Misconceptions & Rules

The static keyword is one of the most misunderstood features in Java. Let’s break it down clearly.

βœ… JVM Behavior:

  • When JVM loads your class, it immediately loads all static methods and variables into the Method Area.

  • These are accessible even without creating an object.

❌ Common Misconception:

"Static methods cannot access the heap."

Not true. Static methods can access heap memory β€” as long as they reference an object.

But here's the key rule:

❗ You cannot use non-static members directly inside a static method.

Why?

Because static methods are not tied to any object instance. They belong to the class, not to a particular object. And since instance variables require an object, they can't be used unless you explicitly refer to an object.

Example:

class Example {
    int x = 10;
    static void printX() {
        // System.out.println(x); ❌ Invalid
        Example e = new Example();
        System.out.println(e.x); βœ… Valid
    }
}

πŸ‘‘ The Object Class – Root of All Java Objects

In Java, every class implicitly extends java.lang.Object.

This is why:

  • Every class has methods like toString(), equals(), and hashCode()

  • All containers (List, Set, Map) inherit from Object

  • JVM treats Object as the ultimate superclass

ArrayList<String> list = new ArrayList<>();

Here, the ArrayList object is created in heap. But internally, it derives from Object, giving it polymorphic behavior.

βœ… Java is object-oriented β€” but not 100% β€” because it supports primitive types (int, char, boolean, etc.).

These primitives are not objects. That’s why Java is said to be "not purely object-oriented."

Still, Java gives you Wrapper Classes (Integer, Character, Boolean) to treat primitives as objects when needed.


πŸ›  How Does Input Reach main() from the Command Line?

Whenever you run:

java Demo Hello World

The arguments "Hello" and "World" are passed as a string array to your main method.

public static void main(String[] args) {
    System.out.println(args[0]); // Hello
    System.out.println(args[1]); // World
}

JVM automatically reads input from stdin, splits it by spaces, and places each token into the args[] array.


βœ… Recap Table

Memory AreaStoresThread Scope
Method AreaStatic data, class structure, bytecodeShared
HeapObjects and instance fieldsShared
StackLocal variables, method callsPer Thread

πŸ§‘β€πŸ’» Final Thoughts

By now, you should be able to visualize exactly what happens:

  • When the JVM loads a class

  • How static methods and variables are stored

  • Where objects go (heap)

  • Why you can’t access non-static things from static methods

  • And how everything starts from Object

Understanding these internals helps you debug more intelligently, write more performant code, and prepare confidently for interviews.

0
Subscribe to my newsletter

Read articles from Arsh Ghaiwat directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Arsh Ghaiwat
Arsh Ghaiwat

Associate System Engineer | Currently learning Java & building fun side projects | Blogging my dev journey to revise, reflect, and grow πŸ‘¨β€πŸ’»πŸš€