2

I have come into a situation where I want to conditionally load and resolve a class. Loading it is as easy as getting a handle to the correct ClassLoader and calling the loadClass method. after calling the loadClass method, I get a valid handle to the class I wanted to load. However, the target class' static intializers are not getting invoked because the class is not being resolved until later. Unfortunately, the classes static initializers register important callbacks. An example of this is shown below.

public class ClassA
{
    public static void main(String[] args) throws Throwable
    {
        Class<?> classB = ClassA.class.getClassLoader().loadClass("ClassB");
        System.out.println(classB.getName());
    }

}

public class ClassB
{
    static
    {
        System.out.println("Class B initializer.");
    }
}

The output of running ClassA in this example is of course:ClassB

I have found a temporary workaround which is (in my opinion) a bit of a hack and that is to call an unimportant static function in ClassB which forces the the class to be resolved. This method is shown below.

public class ClassA
{
    public static void main(String[] args) throws Throwable
    {
        Class<?> classB = ClassA.class.getClassLoader().loadClass("ClassB");
        classB.getMethod("something").invoke(null);
        System.out.println(classB.getName());
    }
}

public class ClassB
{
    static
    {
        System.out.println("Class B initializer.");
    }
    public static void something(){}
}

The output from this method is (as expected):

Class B Initializer.
ClassB

This method has many problems with it such as I have to depend on the class having a public static function, and worry about any side effects of calling that function. Is there a more legitimate way to force classes to resolve?

  • Don't rely 100% on the time of the console. I've seen it run fast and I've seen it run real slow. It needs to output everything in the order they are received. Even sometimes when the gc runs it was pause the console output and input for a second or two – mrres1 Feb 15 '14 at 06:48
  • What I cannot understand is why you need to return the "Class B initializer". There must be a faster way to do what you're currently massacring with ancient static blocks lol – mrres1 Feb 15 '14 at 06:51
  • what do you mean by `return the "Class B Initializer"`? and in what way are static blocks slow –  Feb 15 '14 at 06:59

1 Answers1

2

You can use Class.forName(..) to have your class initialized and get a reference to its Class object.

Class<?> classB = Class.forName("ClassB");

The javadoc states

A call to forName("X") causes the class named X to be initialized.

Related:

Community
  • 1
  • 1
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724