When a .java class is compiled, it gets converted into a .class file which sits in the file system of your computer waiting to be loaded into the Java Virtual Machine (JVM). Now the question is, When are classes loaded in Java? There are two answers to this question:

  • Java classes are loaded in the JVM on demand. This technique of class loading is also called as Lazy Class Loading.
  • All the Java classes comprising the application code are loaded at startup. This technique of class loading is also called as Eager Class Loading.

In this post, I’ll talk about lazy class loading. This is the most widely used type of class loading in all JVM implementations. The biggest advantage of lazy class loading is that it saves memory of JVM. To understand better, let’s say there is a code section in your program which looks like following:

if(result != null)
{
  SomeClass object = new SomeClass();
  // do something....
}

In the above code, if result = null, the code inside the if-block will never be executed. In such a situation, the JVM will never load SomeClass in memory. The program does not demand it….do not load it….save memory… Simple!!

Since theory is best understood when in action, let’s create a program to better understand lazy class loading in Oracle Java HotSpot VM.

Note
The JVM implementation by Oracle (originally developed by SUN) is called the Java HotSpot VM and it implements lazy class loading.

Create a Java project in Eclipse with the following structure:

Create a Java project in Eclipse for lazy class loading

Following is the code for all the classes in the above project:

ChildClass.java
package com.planetofbits.classloading.demo;

public class ChildClass
{
	// Default constructor
	public ChildClass()
	{
		System.out.println("ChildClass: constructor called...");
	}

	public void childClassMethod()
	{
		System.out.println("Inside childClassMethod()...");
	}
}
ClassWithStaticField.java
package com.planetofbits.classloading.demo;

public class ClassWithStaticField
{
	public static String staticField;

	// Default constructor
	public ClassWithStaticField()
	{
		System.out.println("ClassWithStaticMethods: constructor called...");
	}
}
ClassWithStaticMethods.java
package com.planetofbits.classloading.demo;

public class ClassWithStaticMethods
{
	// Default constructor
	public ClassWithStaticMethods()
	{
		System.out.println("ClassWithStaticMethods: constructor called...");
	}

	public static void staticMethod()
	{
		System.out.println("Inside staticMethod()...");
	}
}
ParentClass.java
package com.planetofbits.classloading.demo;

public class ParentClass
{
	// Default constructor
	public ParentClass()
	{
		System.out.println("ParentClass: constructor called...");
	}

	public void callChildClassInstanceMethod()
	{
		System.out.println("Inside callChildClassInstanceMethod()...");
		ChildClass childClass = new ChildClass();
		childClass.childClassMethod();
	}
}
SimpleClass.java
package com.planetofbits.classloading.demo;

public class SimpleClass
{
	public SimpleClass()
	{
		System.out.println("SimpleClass: constructor called...");
	}
}

And finally, ClassLoadingDemo.java is the class which contains the main() method

ClassLoadingDemo.java
package com.planetofbits.classloading.demo;

public class ClassLoadingDemo
{
	public static void main(String[] args)
	{
		System.out.println("Inside main()...");

		// 1. Create an object of a class
		SimpleClass loadThisClass = new SimpleClass();

		// 2. Call a static method
		ClassWithStaticMethods.staticMethod();

		// 3. Access a static field of a class
		ClassWithStaticField.staticField = "Static field assigned a value";

		// 4. Call an subclass instance method
		ParentClass parentClass = new ParentClass();
		parentClass.callChildClassInstanceMethod();
	}
}

Now, we want that the JVM should notify us whenever it loads a class. The -verbose:class option enables logging of class loading. If this command-option is given to the JVM before program execution, it will display a statement on the console whenever it loads a class during the course of program execution.

To do so, right-click on the project name and go to Run As -> Run Configurations…

Maintain Run Configurations

In the left pane, Go to Java Application and right-click on the option New to create a blank run configuration.

Create new run configuration

Provide any name for the new run configuration and also provide main class by clicking on the Search button. The main class in this project is the ClassLoadingDemo.java file.

Provide details for new run configuration

Click on the Arguments tab and in the VM arguments: section type -verbose:class. Click on Apply -> Run to begin execution.

Provide verbose command for new run configuration

While the program executes, the JVM will display in the console view all the classes which are loaded from the begining to end of the program. A sample output screen is shown below.

Output of lazy loading demo

As you can see in the above output, the JVM loads the classes as and when they are used in the program. Each class that gets loaded may have other classes that it depends on, so the loading process is recursive. When the callChildClassInstanceMethod() of ParentClass is called, it causes the loading of the ChildClass because it is being instantiated in that method. Likewise, when a static method or a static field of a class is accessed, it causes the loading of that class.

When are classes loaded in Java

Comments, Questions or Suggestions: