Understanding the Class Loading and Execution Flow in Java

Introduction

This article explains class loading and execution flow in Java. We use a simple example to understand the concept. The NetBeans IDE is used for the sample program.

What is class loading

Class loading is the mechanism through which we load a class into memory at runtime.

Java classes are loaded in one of two ways:

  • By explicit introduction
  • By implicit reference

In the first approach the name of the class to be loaded is explicitly provided to the JRE, one class of each app needs to be explicitly introduced.

In the second approach, a class is loaded implicitly by the JRE whenever a reference of it is encountered for the first time in an already loaded class.

Let's understand how it works

We define two classes in Java named "A.java" and "B.java". The A.java class is loaded directly and B.java is loaded by its object reference, as shown below:

A.java

class A
{
public static void main(String arr[])
{
B x=new B();
B y=new B();
.....
.....
}
}

B.java

class B
{
------
------
}

Understand their loading mechanism through the following figure.

fig-1.jpg

1.0: class A is being explicitly introduced to JRE.

1.1: A class is located and its contents are loaded into memory for execution.

1.2: During the execution of A, first the reference of B is encountered.

1.3: B is loaded to perform the task represented by the reference.

When the class is loaded the following is performed by the JRE:

  • Static data members (if any) are created.
  • Static blocks (if defined) are executed.
  • The task that results in class loading is performed.

Let's use an example

In this example we created the four classes "A", "B", "C" and "D". Now the purpose of creating these four classes is to describe the class loading concept. In the main class "D" we load various classes in various ways as shown below.

The following procedure must be done in the Netbeans IDE.

Step 1

Open the NetBeans IDE.

fig-2.jpg

Step 2

Now select "New Project" from the menu as shown below.

fig-3.jpg

Step 3

Now a new window is generated; select "Java" -> "Java Application" as shown below.

fig-4.jpg

Step 4

Now click on "Next" and give your project heading. I provided "ClassLoadingDemo" and click on "Finish". Your project with default file "ClassLoadingDemo.java" is created as shown below.

fig-5.jpg

Step 5

Now delete this Java file and create a new Java file by right-clicking on "classloadingdemo Package" then select "New" -> "Java Class" as shown below.

fig-6.jpg

Step 6

Now type our class name as "A" as shown below.

fig-7.jpg

Step 7

Now click on "Finish" and write the following code over there.

fig-8.jpg

Step 8

Similarly create another file named "B" and write the following code there.

fig-9.jpg

Step 9

Create another file "C" and write the following code there.

fig-10.jpg

Step 10

Create a new file "D" and write the following code there.

fig-11.jpg

Step 11

Now run the file and see the output.

fig-12.jpg

Note:

Creation of a reference variable doesn't result in a class reference because the implicit type of each variable is integer.

Program Flow

Now from the output of the program we understand the flow of the program.

From "D.java" as the main class we need to understand the flow of class loading. As we know the compiler starts execution at main method. So we check each line one by one after the main method is defined.

1. Class D is load directly since it contains the main method. After class loading we know that the first static block is executed. So it displays the print method that shows "D is initialized.".

2. Now the main method is called and encounters the print method in the first line so it prints "Instantiating A..".

3. Then a reference of class "A" is found so the compiler loads the class A. In the class load we know that static data members (if any) are created, static blocks (if any) are executed and the task we specified is performed.

So it executes the static block and the print method displays "A is initialized." and as we load the class by reference the constructor initializes it automatically and displays "A is instantiated.".

4. Now the compiler returns to the class D and goes to the next line then the compiler finds the print method; they print the string "B value is: ". But it contains a method "value" of class B.

So the compiler loads class "B" into memory and executes its static block that contains value=5, they load the value into memory and goes to the next line and displays the print method as "B is initialized..." and then it prints the static data member as "5".

5. Now the compiler finds the print method so it displays the string "Invoking display() of C.".

6. Now there is a method called "display" which is of class "C". So class C is loaded by the compiler. We know the class is loaded then the static block is automatically executed so it prints "C is initialized..". and prints the display method string as "display() of c invoked.".

7. Now it the print method displays "Instantiating A again.".

8. We create again a reference of class A. But we all know that a class is loaded only once by the compiler at run-time. So when the class is already loaded the static block is not executed again, since it is the property of the static block that it is executed once when the class is loaded the first time. So this time only the constructor is executed and prints "A is instantiated.".

Summary

The main concept of designing this article is to explain how class loading works. By the example I hope you understand it well. Thanks for reading.