Chapter[8]: How Does the JVM Run a Java Program? A Beginner-Friendly Guide Using a Car Object

--

You might have wondered: How does my program run? How does the JVM handle my code, create objects, and manage memory? Don’t worry! Let’s break it all down using a simple Car class example(as we use to do).

The Car Program

We’ll be working with the following program. It introduces the concepts of classes, objects, methods, static and non-static members, and how Java handles memory.

public class Car {  // A Car class is created like this
public String color; // anyone can see the car's color
private int mileage; // only the car owner knows its mileage
public static int carCount = 0; // shared by all cars

public Car(String color, int mileage) { // A Constructor, help create an object with proper parameters
this.color = color; // public in nature
this.mileage = mileage; // private in nature
carCount++; // count each new car (static in nature)
}
// Public method to start the engine
public void startEngine() {
System.out.println("Engine started.");
}
// Private method for an internal fuel check
private void checkFuel() {
System.out.println("Fuel level is sufficient.");
}
// Public method to get the mileage
public int getMileage() {
return mileage; // allows limited access to private mileage
}
public static void main(String[] args) { //JVM runs the code from here
Car myCar = new Car("Red", 15000); // create a new car
myCar.startEngine(); // start the engine
System.out.println("Car color: " + myCar.color); // access public attribute
System.out.println("Car mileage: " + myCar.getMileage()); // get mileage through a public method
System.out.println("Total cars: " + Car.carCount); // access static variable
}
}

Step-by-Step: How the JVM Executes the Program

Let’s break down what happens when the JVM runs the program.

1. Finding the Entry Point

The JVM always looks for the main method as the program's starting point. This method must be static, meaning it can be called without creating an object of the class.

Why static?
If main weren’t static, the JVM would need an object to call it, and to create an object, it would need another method to execute first. This would create a chicken-and-egg problem! By making main static, the JVM can directly access and execute it.

2. Loading the Class

Before executing the main method, the JVM loads the Car class into memory:

  • The Static Area stores the carCount variable since it’s marked as static.
  • The Methods Area prepares the code for all methods (startEngine, getMileage, etc.) so they can be executed when called.

At this point, no objects are created yet. Only the class blueprint is loaded.

3. Executing the main Method

Once the main method is loaded, the JVM starts executing its code line by line:

a. Creating an Object

The line:

Car myCar = new Car("Red", 15000);
  • new Keyword: This tells the JVM to create an object of the Car class.
  • Constructor Call: The Car constructor is executed to initialize the object:
  • color is set to "Red".
  • mileage is set to 15000.
  • carCount is incremented to 1.

The object is stored in the Heap memory, and the reference variable myCar is stored in the Stack memory.

Diagram of the Reference

Stack Memory          Heap Memory                   Class Area
+----------+ +-------------------+ +-----------------+
| myCar | --------> | Object: myCar | | Static: carCount|
| (ref) | |-------------------| | Value: 1 |
+----------+ | color: "red" | +-----------------+
| mileage: 5000 |
+-------------------+

b. Starting the Engine

The line:

myCar.startEngine();
  • The JVM finds the startEngine method in the Methods Area and executes it.
  • It prints:
    “Engine started.”

c. Accessing Public Variables

The line:

System.out.println("Car color: " + myCar.color);
  • Since color is public, the JVM directly accesses it from the object in the Heap.
  • It prints:
    “Car color: Red”

d. Getting Private Variables

The line:

System.out.println("Car mileage: " + myCar.getMileage());
  • The mileage variable is private, so it cannot be accessed directly.
  • Instead, the JVM calls the public getMileage method, which returns the value of mileage.
  • It prints:
    “Car mileage: 15000”

e. Accessing Static Variables

The line:

System.out.println("Total cars: " + Car.carCount);
  • The carCount variable is static, meaning it belongs to the class and not any specific object.
  • The JVM accesses it directly using the class name (Car.carCount) and prints:
    "Total cars: 1"

Memory Management: Where Does Everything Go?

Here’s how the JVM organizes memory for this program:

Memory Areas:

1: Static Area:

  • Stores the carCount variable, shared by all objects.
  • Exists as long as the class is loaded.

2: Heap Memory:

  • Stores the Car object (myCar) and its instance variables (color and mileage).
  • Each object gets its own space in the Heap.

3: Stack Memory:

  • Stores reference variables (myCar) pointing to objects in the Heap.
  • Also holds local variables during method execution.

Line Diagram for Visualization

Here’s a simplified representation of the memory layout after creating one Car object:

               +----------------+
| Car Class |
+----------------+
| Static: |
| carCount = 1 | <-- Shared by all objects
+----------------+
| Constructor |
| Methods: |
| - startEngine()|
| - getMileage() |
+----------------+

Instance: "myCar"
--------------------------------------------
| | |
+-------------+ +--------------+ +-------------+
| myCar | | myCar | | Static Area |
+-------------+ +--------------+ +-------------+
| color: Red | |mileage: 15000| | carCount: 1 |
+-------------+ +--------------+ +-------------+

Static vs Non-Static (Instance)

Static Variables and Methods

1: Belong to the Class:

  • Static variables and methods are associated with the class itself, not individual objects of the class. They are shared among all instances of the class.

2: Accessed Through the Class Name:

  • Static variables and methods should be accessed using the class name (e.g., Car.carCount).
  • While it is technically possible to access them using an object reference (e.g., myCar.carCount), this is not recommended because it can be misleading. It suggests that the variable or method belongs to the object, which is incorrect.

3: Example:

  • A static variable like carCount might be used to track the total number of Car objects created, irrespective of the specific instance.

Instance Variables and Methods

  • Belong to individual objects.
  • Each object has its own copy.
  • Example: color and mileage are specific to each Car object.

Why is main Static?

The main method is static so that the JVM can execute it without needing an object. The program starts here, and objects are created only when explicitly instructed (e.g., using new Car(...)).

Summary of Key Concepts

  1. JVM Entry Point: The main method must be static so the program can start without creating an object.
  2. Object Creation: Objects are created only when the new keyword is used.
  3. Memory Management:
  • Static Variables: Stored in the Static Area, shared by all objects.
  • Instance Variables: Stored in the Heap, unique to each object.
  • Stack Memory: Holds reference variables and local method variables.
  1. Access Modifiers:
  • Public: Can be accessed from anywhere.
  • Private: Only accessible within the class.
  1. Static vs Instance:
  • Use static for shared data or behaviors (e.g., carCount).
  • Use instance variables for object-specific data (e.g., color).

Memory Diagram Explanation:

1. Class Area:

  • Stores static variables and methods that are shared among all objects.
Class: Car
+---------------------------+
| static carCount: 1 | (shared by all instances)
+---------------------------+

2. Heap Memory:

  • Stores the actual objects and their instance variables.
Heap Memory
+---------------------------+
| Object: myCar |
|---------------------------|
| color: "Red" | (public instance variable)
| mileage: 15000 | (private instance variable, accessed via getMileage())
+---------------------------+

3. Stack Memory:

  • Stores references to objects and method call information.
Stack Memory
+---------------------------+
| Method: main() |
|---------------------------|
| myCar -> (points to heap) |
+---------------------------+

With this detailed breakdown, you should now understand how the JVM processes a program like our Car example, manages memory, and executes your code. The magic of Java lies in its structure and the JVM’s ability to handle all this complexity behind the scenes! 🚗

Happy Coding

--

--

Automate This. By Mrigank Saxena
Automate This. By Mrigank Saxena

Written by Automate This. By Mrigank Saxena

Join me as I share insights, tips, and experiences from my journey in quality assurance, automation, and coding! https://www.linkedin.com/in/iammriganksaxena/

No responses yet