Class.forName() vs ClassLoader.loadClass() - which to use for dynamic loading?

JavaClassloader

Java Problem Overview


When dynamically loading a class, when is it appropriate to use

Class.forName("SomeClass");

and when should I use

ClassLoader.getSystemClassLoader().loadClass("SomeClass");

Or, are they two ways of doing the same thing?

Java Solutions


Solution 1 - Java

They are quite different!

As stated in the documentation for Class.forName(String),

> Returns the Class object associated with the class or interface with the given string name. Invoking this method is equivalent to: Class.forName(className, true, currentLoader)

(true here refers to do you want to initialize the class?)

On the other hand, ClassLoader.loadClass(String):

> Invoking this method is equivalent to invoking loadClass(name, false).

(here, the boolean has nothing to do with initialization; but if you check loadClass(String, boolean) documentation, you will see that all it does is load the class, not initialize it).

The first one (Class.forName("SomeClass");) will:

  • use the class loader that loaded the class which calls this code
  • initialize the class (that is, all static initializers will be run)

The other (ClassLoader.getSystemClassLoader().loadClass("SomeClass");) will:

  • use the "system" class loader (which is overridable)
  • not initialize the class (say, if you use it to load a JDBC driver, it won't get registered, and you won't be able to use JDBC!)

Suppose you are coding a web application that will be executed on a container such as Tomcat. What Tomcat does is create a class loader for each web application (so that it can unload the webapps later and release memory -- you need a dedicated class loader for this to work!). In this situation, you can see that both calls will yield quite different results!

For more detailed (and authoritative) information on class loading and initialization, check sections 12.2 and 12.4 of the latest (3rd) edition of the Java Language Specification.

Solution 2 - Java

Class.forName() uses the caller's classloader and initializes the class (runs static intitializers, etc.)

loadClass is a ClassLoader method, so it uses an explicitly-provided loader, and initializes the class lazily (on first use).

Note that there's a Class.forName() that also takes a ClassLoader.

Solution 3 - Java

They are basically doing the same thing. The ClassLoader used may be different though. Class.forName uses the ClassLoader you get from this.getClass().getClassLoader() whereas your other code specifies to use the system class loader.

In most applications this will be the same class loader but in more complicated environments such as a J2EE app or an applet this may not be the case.

Solution 4 - Java

  • Class.forName() load and initialize the class. In class loader subsystem it executes all the three phases i.e. load, link, and initialize phases.

  • ClassLoader.loadClass() behavior, which delays initialization until the class is used for the first time. In class loader subsystem it executes only two phases i.e. load and link phases.

For example:

class MyClass {
	static {
		System.out.println("static block in MyClass");
	}
}

public class TestCase1 {
	public static void main(String... args) throws Throwable {
		Class.forName("A");
	}
} //The above TestCase1 produce output: static block in MyClass

public class TestCase2 {
	public static void main(String... args) throws Throwable {
		ClassLoader.getSystemClassLoader().loadClass("MyClass");
	}
} //The above TestCase2 not produce any output

Solution 5 - Java

ClassLoader is an abstract class, however your application is always loaded by a classloader, there could be custom class loaders such as network classloader or any other source.

On the other hand Class in itself represents classes and interfaces and the class Class has a forName function that uses the current class loader in which your application is running by default to load the class.

Here is the source for the Class.forName which in turn invokes the calling classloader.

public static Class<?> forName(String className)
            throws ClassNotFoundException {
    return forName0(className, true, ClassLoader.getCallerClassLoader());
}

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ClassLoader.html

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#forName(java.lang.String)

Hint: Primordial class loader http://docs.oracle.com/javase/1.4.2/docs/guide/security/spec/security-spec.doc5.html

Solution 6 - Java

I love Class loading in java...

It really depends on what context the application is being run in. You will get different results if you are using it from a web context as opposed to just a command line program.

I've also run into problems depending on what your ClassPath looks like and what I was expecting to happen.

This JavaWorld article explains a good deal about it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionZackView Question on Stackoverflow
Solution 1 - JavaBruno ReisView Answer on Stackoverflow
Solution 2 - JavaDave NewtonView Answer on Stackoverflow
Solution 3 - JavaSarel BothaView Answer on Stackoverflow
Solution 4 - JavaPremrajView Answer on Stackoverflow
Solution 5 - Javar0ast3dView Answer on Stackoverflow
Solution 6 - JavaCaseyView Answer on Stackoverflow