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.
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:
Following is the code for all the classes in the above project:
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()..."); } }
package com.planetofbits.classloading.demo; public class ClassWithStaticField { public static String staticField; // Default constructor public ClassWithStaticField() { System.out.println("ClassWithStaticMethods: constructor called..."); } }
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()..."); } }
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(); } }
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
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…
In the left pane, Go to Java Application and right-click on the option New to create a blank 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.
Click on the Arguments tab and in the VM arguments: section type -verbose:class
. Click on Apply -> Run to begin execution.
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.
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.