views:

552

answers:

1

Hello,

I have an URLClassLoader named "MyClassLoader" set up with some jars on it. If I try

MyClassLoader.loadClass("MyClass");

it works.

If I try

Thread.currentThread().setContextClassLoader(MyClassLoader);
Thread.currentThread().getContextClassLoader().loadClass("MyClass");

it also works.

But If I try

Thread.currentThread().setContextClassLoader(MyClassLoader);
Class.forName("MyClass");

it throws a ClassNotFoundException.

Of course, Class.forName here is just an example; trying to use MyClass throws the exception just as well.

All this probably means I don't understand how setContextClassLoader works. Could anyone clarify this to me and help me understand it - and what should I do to make my code work? Thank you.

+1  A: 

public static Class forName(String className) throws ClassNotFoundException

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) where currentLoader denotes the defining class loader of the current class.

Try:

Class.forName("MyClass", true, MyClassLoader);

[Class.forName(String, boolean, ClassLoader][1]

The likely problem you are encountering is that you are trying to forName a Class that you loaded with a custom ClassLoader. However, you are using the form of forName that implicitly uses the ClassLoader which loaded the Class making the call. In most cases, this will be the system ClassLoader.

ClassLoaders can get complex.

[1]: http://java.sun.com/javase/6/docs/api/java/lang/Class.html#forName(java.lang.String, boolean, java.lang.ClassLoader)

Tim Bender
Yes, Class.forName is one of those methods listed in section 6 of the secure coding guidelines as behaving strangely dependent upon the caller class loader. Not that methods that depend upon the thread context class loader at any better. The smart thing to is use a class loader explicitly.
Tom Hawtin - tackline