7

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?

Jacob Schoen
  • 14,034
  • 15
  • 82
  • 102
Michał
  • 145
  • 1
  • 4
  • 12
  • can you post the exception and stack trace that you get? – Shaunak Mar 13 '12 at 20:50
  • Of course: 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) – Michał Mar 13 '12 at 20:56

3 Answers3

4

The above answers are both wrong, they don't understand the root problem. Your main refers to the Stack class which was loaded by one class loader. Your urlclassloader is attempting to load a class with the same name. You cannot cast the loaded to the referred because they are not the same, they belong to different classloaders. You can print the has code of each to see they are different. An equality test will also show the cclass references to be different. Your problem is probably because dependent classes referenced by sstack can be found, which will result in NoClassDefErrors etc. Your main will probably fail with a classcastexception.

carlspring
  • 31,231
  • 29
  • 115
  • 197
mP.
  • 18,002
  • 10
  • 71
  • 105
2
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.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • So how i can use method from this class? – Michał Mar 13 '12 at 21:07
  • @user1267483 You would need to create an interface in the the project that you are using URLClassloader for Stack, that your michal.collection.Stack implements. – Jacob Schoen Mar 13 '12 at 21:21
  • @user1267483 Note, I've changed the name of `Stack` to `StackImpl` (not the best name, but conventional), and introduced a new interface, `Stack`. – Tom Hawtin - tackline Mar 13 '12 at 21:40
  • I see. Thank you very much for help. I had second problem because my class Stack is Template but I solve this problem myself. – Michał Mar 13 '12 at 22:36
0

You can't refer to the dynamically-loaded type by name in the code, since that has to be resolved at compile-time. You'll need to use the newInstance() function of the Class object you get back from loadClass().

VeeArr
  • 6,039
  • 3
  • 24
  • 45