104

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?

Zack
  • 6,232
  • 8
  • 38
  • 68

6 Answers6

168

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.

Community
  • 1
  • 1
Bruno Reis
  • 37,201
  • 11
  • 119
  • 156
  • 4
    +1, lots more details :) – Dave Newton Nov 11 '11 at 21:54
  • 3
    I found this out the hard way, and can assuredly confirm that this is the case using Catalina. I had called `getClassLoader().loadClass("...");` on a `Class` type to attempt to load a Torque peer class in order to run a static initializer block which maps the peer to a database table. The static block was not executed on this call. However, upon calling `Class.forName("...");` for the peer class the static block was executed. +1 for a good explanation and educating me as to why I ran into this issue! – jbowman Jul 15 '14 at 18:01
10

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.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
  • Hello Dave, could you please tell me the difference between "caller's classloader" and "explicitly-provided loader". Thanks – Jaikrat Jun 09 '15 at 13:30
  • @Jaikrat An "explicitly-provided classloader" is a class loader that you provide, e.g., you must call `loadClass` using a `ClassLoader` instance, like `myClassLoader.loadClass(String)`. There are other difference as explained in the accepted answer. – Dave Newton Jun 09 '15 at 13:33
2
  • 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
Premraj
  • 72,055
  • 26
  • 237
  • 180
0

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.

Sarel Botha
  • 12,419
  • 7
  • 54
  • 59
-1

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

r0ast3d
  • 2,639
  • 1
  • 14
  • 18
-3

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.

Casey
  • 12,070
  • 18
  • 71
  • 107
  • 4
    That's a bit different than what's being asked, I think? – Dave Newton Nov 11 '11 at 21:54
  • Well I linked to that article as it is one I've read in the past and helped answer some of the issues I had with class loading. – Casey Nov 11 '11 at 22:03
  • 1
    I understand (and think a downvote is a little harsh), but the question was specifically about the differences between `forName` and `loadClass`, which the article doesn't discuss (I don't think the word `forName` even shows up). I'm not mad or anything, I'm just not sure it's on-topic :) – Dave Newton Nov 11 '11 at 22:11