Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between Loading a class using ClassLoader and Class.forName

Tags:

Below are 2 code snippets

The first one uses ClassLoader class to load a specified class

ClassLoader cls = ClassLoader.getSystemClassLoader(); Class someClass = cls.loadClass("TargetClass");

The second one uses Class.forName() to load a specified class

Class cls = Class.forName("TargetClass");

What is the difference between the above said approaches. Which one serves for which purpose?

like image 575
Ebbu Abraham Avatar asked Nov 26 '10 13:11

Ebbu Abraham


People also ask

Which ClassLoader is used to load a class?

Types of ClassLoaders in Java To know the ClassLoader that loads a class the getClassLoader() method is used. All classes are loaded based on their names and if any of these classes are not found then it returns a NoClassDefFoundError or ClassNotFoundException.

Is it possible to load a class by two ClassLoader?

A class is always identified using its fully qualified name (package. classname). So when a class is loaded into JVM, you have an entry as (package, classname, classloader). Therefore the same class can be loaded twice by two different ClassLoader instances.

What is purpose of class forName () method?

forName. Returns the Class object associated with the class or interface with the given string name, using the given class loader. Given the fully qualified name for a class or interface (in the same format returned by getName ) this method attempts to locate, load, and link the class or interface.

When would you use a ClassLoader?

Java uses ClassLoader implicitly when you use new , import keyword, the jvm will use the current class's classloader to load the dependent classes, so you can use the custom classloader to load a bootstrap class explicitly by using classloader.


1 Answers

The other answers are very complete in that they explore other overloads of Class.forName(...), and talk about the possibility to use different ClassLoaders.

However they fail to answer your direct question: "What is the difference between the above said approaches?", which deals with one specific overload of Class.forName(...). And they miss one very important difference. Class initialization.

Consider the following class:

public class A {   static { System.out.println("time = " + System.currentTimeMillis()); } } 

Now consider the following two methods:

public class Main1 {   public static void main(String... args) throws Throwable {     final Class<?> c = Class.forName("A");   } }  public class Main2 {   public static void main(String... args) throws Throwable {     ClassLoader.getSystemClassLoader().loadClass("A");   } } 

The first class, Main1, when run, will produce an output such as

time = 1313614183558 

The other, however, will produce no output at all. That means that the class A, although loaded, has not been initialized (ie, it's <clinit> has not been called). Actually, you can even query the class's members through reflection before the initialization!

Why would you care?

There are classes that performs some kind of important initialization or registration upon initialization.

For example, JDBC specifies interfaces that are implemented by different providers. To use MySQL, you usually do Class.forName("com.mysql.jdbc.Driver");. That is, you load and initialize the class. I've never seen that code, but obviously the static constructor of that class must register the class (or something else) somewhere with JDBC.

If you did ClassLoader.getSystemClassLoader().loadClass("com.mysql.jdbc.Driver");, you would not be able to use JDBC, since the class, altough loaded, has not been initialized (and then JDBC wouldn't know which implementation to use, just as if you had not loaded the class).

So, this is the difference between the two methods you asked.

like image 179
Bruno Reis Avatar answered Oct 20 '22 05:10

Bruno Reis