Click to See Complete Forum and Search --> : Creating a ClassLoader?
Dillinger4
Oct 7th, 2003, 10:59 PM
This is an excerpt from an interesting artice i found inside a recent Java Developers Journal( Aug 2003 Vol:9 Issue:8) magazine.
The loadClass(String classname) method invokes the
findClass(String classname) method. Custom ClassLoaders
shoud override this method to provide a custom way of
locating and loading a Java class file.
:ehh: Ok sounds easy enough but i have a few questions. Am i doing this right? :D How can i scope the size of the byte array to the number of bytes within the file? Once the class is returned from the classloader how can i execute it? More questions to come......... :lol:
import java.io.*;
public class Loader extends ClassLoader{
private byte[] b;
public Class findClass(String c) throws ClassNotFoundException{
try{
Scanner s = new Scanner(c);
this.b = s.getByteCode();
}catch(IOException e){;}
return b.getClass();
}
}
public class Scanner{
private File res;
public Scanner(String r){
res = new File(r);
}
public byte[] getByteCode() throws IOException{
BufferedInputStream buff;
buff = new BufferedInputStream(new FileInputStream(res));
byte[] b = new byte[5000];
long bytesread = 0;
while(true){
bytesread = buff.read(b);
if(bytesread < 0) break;
}
return b;
}
}
CornedBee
Oct 9th, 2003, 02:29 AM
Doesn't the File class have a getLength method or some such?
I think I'll experiment with this a bit too.
Dillinger4
Oct 9th, 2003, 10:44 PM
byte[] b = new byte[res.length()]; compiles fine. Now im in the process of trying to figure out how to execute the class that is returned by the claassloader. I lost my Java docs. :mad: Any ideas? Thanks.
CornedBee
Oct 10th, 2003, 01:23 AM
Class.createInstance?
Dillinger4
Oct 10th, 2003, 01:04 PM
From what they are saying the loadClass method invokes the find class method. The find class method searches for the given class in the repository and if found reads and returns the byte codes for the class. The raw byte codes are passes to the defineClass() method implemented in the java.lang.ClassLoader Class which returns an instance of the java.lang.Class object.
The chain of events is confusing to me. Do i have to implement all of the methods within the java.lang.ClassLoader Class? Then invoke the findClass() method from the loadClass() method and the defineClass() method from the findClass() method? It makes sense since each one returns a Class object. It sounds like it shoud just be a chain of events emanating from the source. ie. (loadClass());
CornedBee
Oct 10th, 2003, 03:31 PM
Seems quite straightforward to me. You have a CustomClassLoader that extends ClassLoader. To get a Class object you call loadClass on your CustomClassLoader. You don't override this method. The default implementation will then:
1) Check if the class already is loaded. If yes, return class object.
2) Call getParent().loadClass() to delegate the call to other class loaders.
3) If there still is no match, call findClass.
findClass will be overloaded by you. It somehow retrieves a byte array that contains the class bytecode and passes this on to defineClass, which returns a Class object, which findClass passes on to loadClass, which returns it.
You then have a Class object and can do whatever you want with it.
Dillinger4
Oct 12th, 2003, 03:39 PM
This is pretty much what they have. So it seems that the loadClass() method is overridden.
What i dont understand is the check to see if the class is already loaded in the loadClass() method. If findClass() cannot find the class then a ClassNotFoundException is thrown but then the rest of the code in the loadClass() method is skipped.
public class Y{
public static void main(String[] args){
try{
Class c;
Loader l = new Loader();
c = l.loadClass("C:\\Java\\E.class");
}catch(ClassNotFoundException e){System.err.println(e);}
}
}
import java.io.*;
public class Loader extends ClassLoader{
protected Class findClass(String classname) throws ClassNotFoundException{
byte[] classbytes = null;
try{
Scanner s = new Scanner(classname);
classbytes = s.getByteCode();
}catch(IOException e){System.err.println(e);
}
if(classbytes != null){
return defineClass(classname, classbytes,0,classbytes.length);
}
throw new ClassNotFoundException(classname);
}
public Class loadClass(String name) throws ClassNotFoundException{
// check if the class is already loaded
Class loadedclass = findClass(name);
if(loadedclass == null){
// search for class in local repository before delegating
//.........
// if class not found delegate to parent
loadedclass = this.getClass().getClassLoader().loadClass(name);
}
return loadedclass;
}
}
CornedBee
Oct 13th, 2003, 01:22 AM
I don't think you should override loadClass. The docs explicitly say "Subclasses of ClassLoader are encouraged to override findClass(String), rather than this method."
Dillinger4
Oct 13th, 2003, 12:44 PM
Yes i have to agree with you on that one. Everything i have read so far about ClassLoaders has said to just override the findClass() method and keep the default implementation of the loadClass().
method.
Here is what i have so far and it seems to work but only if the class being loaded is in the -classpath dir. If i take the class out of that dir and put in say C:\ a java.lang.ClassNotFoundException is thrown.
So would be correct to say that since the .class file is in dir specified in the -classpath, the system classloader is loading the class thus not executing the findClass() method?
import java.io.*;
public class Y{
public static void main(String[] args){
try{
Class c;
Loader l = new Loader();
c = l.loadClass("E");
String classname = c.getName();
System.out.println(classname);
Object o = c.newInstance();
if(o instanceof E){
E e = (E)o;
e.printFName();
}
}catch(ClassNotFoundException e){System.err.println(e);}
catch(java.lang.InstantiationException ie){System.err.println(ie);}
catch(java.lang.IllegalAccessException iae){System.err.println(iae);}
}
}
import java.io.*;
public class Loader extends ClassLoader{
protected Class findClass(String classname) throws ClassNotFoundException{
byte[] classbytes = null;
try{
Scanner s = new Scanner(classname);
classbytes = s.getByteCode();
}catch(IOException e){System.err.println(e);
}
if(classbytes != null){
return defineClass(classname, classbytes,0,classbytes.length);
}
throw new ClassNotFoundException(classname);
}
}
CornedBee
Oct 14th, 2003, 01:14 AM
Sounds plausible, but you can check that with a debugger.
Dillinger4
Oct 15th, 2003, 06:13 PM
Im using a command line compiler and notepad. :sick:
CornedBee
Oct 17th, 2003, 07:57 AM
So what, I've used the command line debugger before.
Dillinger4
Oct 17th, 2003, 05:24 PM
Never used it. :lol:
vbforums.com
Copyright Internet.com Inc., All Rights Reserved.