Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Class.forName() vs ClassLoader in Java Reflection

Tech 1

Core Difference: Load + Initialize vs Load Only

Class Loading in JVM

Java class loading involves three phases: LoadingLinkingInitialization.

  • Loading: Bytecode is read into memory, creating a Class object.
  • Initialization: Static blocks execute and static variable are assigned (<clinit> method runs).

The two mechanisms differ in which phases they cover:

Aspect Class.forName(String) ClassLoader.loadClass(String)
Default behavior Loads class and triggers initialization Loads class without initialization
Initialization control Overloaded version Class.forName(name, initialize, loader) allows disabling init No control – never triggers init
Exception ClassNotFoundException (checked) ClassNotFoundException (checked)
Class name format Fully qualified name (e.g. java.sql.Driver) Fully qualified name (same)
Implementation Internally calls ClassLoader, then adds initialization step Core loading mechanism; forName depends on it

Code Demo: Observing the Difference

1. Test class with static block

public class SampleClass {
    static {
        System.out.println("SampleClass static block executed (initialization)");
    }

    public static String value = "static field initialized";
}

2. Class.forName() triggers initialization by default

public class DemoForName {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> clazz = Class.forName("com.example.SampleClass");
        System.out.println("Class.forName completed");
    }
}

Output:

SampleClass static block executed (initialization)
Class.forName completed

3. ClassLoader.loadClass() skips initialization

public class DemoLoader {
    public static void main(String[] args) throws ClassNotFoundException {
        ClassLoader loader = ClassLoader.getSystemClassLoader();
        Class<?> clazz = loader.loadClass("com.example.SampleClass");
        System.out.println("ClassLoader.loadClass completed");

        // Access static field triggers initialization
        System.out.println(SampleClass.value);
    }
}

Output:

ClassLoader.loadClass completed
SampleClass static block executed (initialization)
static field initialized

4. Class.forName() with initialization disabled

public class DemoForNameNoInit {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> clazz = Class.forName("com.example.SampleClass", false, ClassLoader.getSystemClassLoader());
        System.out.println("Class.forName (init disabled) completed");
    }
}

Output:

Class.forName (init disabled) completed

Practical Use Cases

When to use Class.forName()

Loading JDBC drivers is the classic example:

Class.forName("com.mysql.cj.jdbc.Driver");

The driver's static block registers the driver with DriverManager. Initialization must happan, so forName() is appropriate.

When to use ClassLoader

  • Lazy initialization – frameworks like Spring or Tomcat load class metadata without triggering static blocks until the class is actually used (e.g., calling a static method or creating an instance).
  • Custom class loaders – in scnearios like hot deployment or modular loading, you only want the loading phase, leaving initialization up to the application logic.

Key Takeaways

  1. Class.forName() loads and initializes (configurable); ClassLoader.loadClass() loads only, never initializes.
  2. Class.forName() wraps ClassLoader internally, adding an initialization step.
  3. Choose forName() when static code must run eagerly (e.g., driver registration); choose ClassLoader when only the class definition is needed and initialization should be deferred.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.