Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Get a load of that name!

Subtle differences in various ways you can dynamically load a class

  • Print
  • Feedback

March 14, 2003

Q What is the difference between Class.forName() and ClassLoader.loadClass()?

A Both methods try to dynamically locate and load a java.lang.Class object corresponding to a given class name. However, their behavior differs regarding which java.lang.ClassLoader they use for class loading and whether or not the resulting Class object is initialized.

The most common form of Class.forName(), the one that takes a single String parameter, always uses the caller's classloader. This is the classloader that loads the code executing the forName() method. By comparison, ClassLoader.loadClass() is an instance method and requires you to select a particular classloader, which may or may not be the loader that loads that calling code. If picking a specific loader to load the class is important to your design, you should use ClassLoader.loadClass() or the three-parameter version of forName() added in Java 2 Platform, Standard Edition (J2SE): Class.forName(String, boolean, ClassLoader).

Additionally, Class.forName()'s common form initializes the loaded class. The visible effect of this is the execution of the class's static initializers as well as byte code corresponding to initialization expressions of all static fields (this process occurs recursively for all the class's superclasses). This differs from ClassLoader.loadClass() behavior, which delays initialization until the class is used for the first time.

You can take advantage of the above behavioral differences. For example, if you are about to load a class you know has a very costly static initializer, you may choose to go ahead and load it to ensure it is found in the classpath but delay its initialization until the first time you need to make use of a field or method from this particular class.

The three-parameter method Class.forName(String, boolean, ClassLoader) is the most general of them all. You can delay initialization by setting the second parameter to false and pick a given classloader using the third parameter. I recommend always using this method for maximum flexibility.

Class initialization errors are tricky

Just because you successfully load a class does not mean there won't be any more problems. Recollect that static initialization code can throw an exception, and it will get wrapped in an instance of java.lang.ExceptionInInitializerError, at which point, the class becomes unusable. Thus, if it is important to process all such errors at a known point in code, you should use a Class.forName() version that performs initialization.

Furthermore, if you handle ExceptionInInitializerError and take measures so that the initialization can be retried, it will likely not work. This code demonstrates what happens:

public class Main
{
    public static void main (String [] args) throws Exception
    {
        for (int repeat = 0; repeat < 3; ++ repeat)
        {
            try
            {
                // "Real" name for X is outer class name+$+nested class name:
                Class.forName ("Main$X");
            }
            catch (Throwable t)
            {
                System.out.println ("load attempt #" + repeat + ":");
                t.printStackTrace (System.out);
            }
        }
    }
    private static class X
    {
        static
        {
            if (++ s_count == 1)
                throw new RuntimeException ("failing static initializer...");
        }
        
    } // End of nested class
    private static int s_count;
} // End of class


This code attempts to load the nested class X three times. Even though X's static initializer fails only on the first attempt, all of them fail:

  • Print
  • Feedback

Resources