Java example with ClassLoader

Michał picture Michał · Mar 13, 2012 · Viewed 22.3k times · Source

I have small problem. I learn java SE and find class ClassLoader. I try to use it in below code: I am trying to use URLClassLoader to dynamically load a class at runtime.

URLClassLoader urlcl = new URLClassLoader(new URL[] {new URL("file:///I:/Studia/PW/Sem6/_repozytorium/workspace/Test/testJavaLoader.jar")});
Class<?> classS = urlcl.loadClass("michal.collection.Stack");
for(Method field: classS.getMethods()) {
     System.out.println(field.getName());
}
Object object = classS.newInstance();
michal.collection.Stack new_name = (michal.collection.Stack) object;

The java virtual machine does not see me class, and I get the following exception:

Exception in thread "main" java.lang.Error: Unresolved compilation problems: michal cannot be resolved to a type michal cannot be resolved to a type at Main.main(Main.java:62)

Do you know how I can solve this problem?

Answer

Tom Hawtin - tackline picture Tom Hawtin - tackline · Mar 13, 2012
Class<?> classS = urlcl.loadClass("michal.collection.Stack");
[...]
Object object = classS.newInstance();
michal.collection.Stack new_name = (michal.collection.Stack) object;

So you're attempting to dynamically load a class and then you statically refer to it. If you can already statically link to it, then its loaded and you can't load it again. You'll need to access the methods by reflection.

What you would usually do is have the loaded class implement an interface from the parent class loader. After an instance is created (usually just a single instance), then you can refer to it through a reference with a type of the interface.

public interface Stack {
   [...]
}
[...]
    URLClassLoader urlcl = URLClassLoader.newInstance(new URL[] {
       new URL(
           "file:///I:/Studia/PW/Sem6/_repozytorium/workspace/Test/testJavaLoader.jar"
       )
    });
    Class<?> clazz = urlcl.loadClass("michal.collection.StackImpl");
    Class<? extends Stack> stackClass = clazz.asSubclass(Stack.class);
    Constructor<? extends Stack> ctor = stackClass.getConstructor();
    Stack stack = ctor.newInstance();

(Usual Stack Overflow disclaimer about not so much as compiling.)

You'll need to add error handling to taste. URLClassLoader.newInstance adds a bit of refinement to URLClassLoader. Class.newInstance has completely broken exception handling and should be avoided.