dynamically loaded class
Hi all, I have loaded a class using a custom class loader, I noted that my class loader loads the intended class and its all inner classes also all classes used in that class-which my class owns a references to instances of them.
at last it seems that my class successfully loaded, but when attempting to create an instance using classObject.newInstance();
method, it throws an InstantiationException
any ideas for solution?
Thanks .
Ahmad Elsafty
From the javadocs for Class.newInstance():
...
InstantiationException - if this Class represents an abstract class, an interface, an array class, a primitive type, or void; or if the class has no nullary constructor; or if the instantiation fails for some other reason.
...
So figure out which one (or more) of those is true for the class you are trying to instantiate.
Thanks for reply warnerja.
I successfully create an instance from the same class at compile time using new operator.
so I am sure that it is a Class, non abstract one, not interface, nor primitive type.
I think the problem is because my loaded class has more than one inner class, because I note that my custom class loader recursive loops to load all classe's inner classes.
Am I true?
Thanks
Ahmad Elsafty
doe it require the classes are serializable?
Can you post the full stack trace, as it is normally kind enough to tell you why it is failing.
mlka at 2007-7-9 5:42:51 >

if you're trying to instantiate an inner class, be aware that inner classes have an implicit constructor that takes an instance of their enclosing type as an argument, to satisfy the "free" relationship between the 2
so class.newInstance won't work. you need to get the constructor object for the inner class that takes the enclosing type, and instantiate from that. eg
public class Outer {
class Inner {
}
}
...
void load() {
Constructor con = Inner.class.getConstructor(new Class[] { Outer.class} );
con.newInstance();
}
Note that when a class wants to load related classes it always asks the ClassLaoder which loaded it, and this will include any interface or superclass that the class implements.
1) Has your class got a no-args constructor?
2) Does your custom classloader delegate correcty? Normally it should be set up with a parent pointer pointing to the system classloader, and it should only load classes itself after checking that the parent classloader can't find them. If you haven't done this right the classloader may not be able to resolve references to a superclass or interface of the main, or one of the inner classes.
Thank you all.1-Due to Serialization, I do not think so2-Due to Full Stack trace, I recieved this huge details from stack trace:Exception:se.bysoft.sureshot.products.jplayer.JPlayer
1) Does your class have a no-argument constructor?2) Does it implement an interface or extend another class? (I believe you'll get this expection if it fails to load either).
> 2-Due to Full Stack trace, I recieved this huge
> details from stack trace:
>Exception:se.bysoft.sureshot.products.jplayer.JPlayer
That is not the full stack trace, that is someone eating the stack trace, and replacing it with ****. Rewrite you exception handler to not output ****.
mlka at 2007-7-9 5:42:51 >

Thanks for reply.
I am using a class as a loader which I copy it from this forum
that is:
public class LibClassLoader extends ClassLoader {
private Hashtable classes = new Hashtable();
private File f;
public LibClassLoader(String zipFileName) {
this (new File(zipFileName));
}
public LibClassLoader(File zipFile) {
f = zipFile;
}
public Class loadClass(String className) throws ClassNotFoundException {
return (loadClass(className, true));
}
public synchronized Class loadClass(String className, boolean resolve) throws ClassNotFoundException {
if (classes.containsKey(className)) return (Class)classes.get(className);
ZipFile zipFile = null;
BufferedInputStream bis = null;
byte[] res = null;
try {
zipFile = new ZipFile(f);
ZipEntry zipEntry = zipFile.getEntry(className.replace('.', '/')+".class");
res = new byte[(int)zipEntry.getSize()];
bis = new BufferedInputStream(zipFile.getInputStream(zipEntry));
bis.read(res, 0, res.length);
} catch (Exception ex) {
} finally {
if (bis!=null) {
try {
bis.close();
} catch (IOException ioex) {}
}
if (zipFile!=null) {
try {
zipFile.close();
} catch (IOException ioex) {}
}
}
if (res == null) return super.findSystemClass(className);
Class clazz = defineClass(className, res, 0, res.length);
if (clazz == null) throw new ClassFormatError();
if (resolve) resolveClass(clazz);
classes.put(className, clazz);
return(clazz);
}
}
I do not know does this class handle class loading correctly or not?
My class does not have a no arguments constructor.
Thanks
Ahmad Elsafty
} catch (Exception ex) {} finally {Never do that.What does the exception handler for this do?
mlka at 2007-7-9 5:42:51 >

Thanks mlk,but you did not tell me if this code handle class loading correctly or not?Thanks.Ahmad Elsafty
AFAIKS this classloader doesn't delegate, even if it fails to find the class. That means it won't successfully load a class with an interface or superclass not in the ZIP file. As part of the process of loading your class any superlclass or interface will be requested from the same classloader. This will not normally be a "system" class.
Normally a custom classloader should first try to get the class from it's parent (getParent().loadClass()) and only if the result is a ClassNotFoundException go on to load the class itself.
@OP: are you sure this is a classloading issue? you don't seem to have addressed the other suggestions (regarding constructors) from the thread
Thank you all,Could any one send me a class loader code to successfully load my class, even it has inner ones, and even it use or inherit an API classes.Thanks again.Ahmad Elsafty
java.net.URLClassLoader generally does the job for you.