MyclassLoader.java
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
public class MyClassLoader extends ClassLoader{
private String filePath;
public MyClassLoader(String filePath){
this.filePath=filePath;
}
protected Class<?> findClass(String className)throws ClassNotFoundException{
Class clazz=this.findLoadedClass(className);
if(null==clazz){//为什么不写clazz==null
try{
byte[] bytes=loadClassBytes(className);
//定义clazz类
clazz=defineClass(className,bytes,0,bytes.length);
}catch(IOException e){
throw new ClassNotFoundException(e.toString());
}
}
return clazz;
}
private byte[] loadClassBytes(String className)throws IOException{
//获取class文件路径
String classFile=getClassFile(className);
System.out.println(classFile);
FileInputStream fis=null;
try {
fis = new FileInputStream(classFile);
} catch (FileNotFoundException e) {
System.out.println(e);
return null;
}
byte[] bytes = new byte[fis.available()];
fis.read(bytes);
fis.close();
return bytes;
}
//将文件路径与文件名组合
private String getClassFile(String name){
StringBuffer sb=new StringBuffer(filePath);
name=name.replace('.',File.separatorChar)+".class";
sb.append(File.separatorChar+name);
return sb.toString();
}
}
MainTest.java
public class MainTest {
public static void main(String[] args) {
try {
MyClassLoader cl = new MyClassLoader("E:\\eclipse\\workspace\\ClassLoader\\bin");
Class c = cl.loadClass("com.Hello");
System.out.println(c.getClassLoader());
Hello hello = (Hello) c.newInstance();
hello.say();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
Hello.java就是我写的一个简单的HelloWorld类,里面的方法say(),输出“hello!”。
Hello.java
public class Hello {
//public static void main(String[] args){
public void say(){
System.out.println("hello!");
}
}
问题出在蓝色字体那一句,如果调用loadClass方法,那么根本就没有运行我自定义的findClass(),而是通过系统AppClassLoader就成功加载了类。那么如果把这句换成Class c = cl.findClass("com.Hello");那么,直接运行我自定义的findClass()方法,但是在MainTest类中Hello hello = (Hello) c.newInstance();这一句会出错,不能转换成Hello类,怎么回事?
------解决方案--------------------------------------------------------
看看classloader的委托模型:http://www.ticmy.com/?p=257
------解决方案--------------------------------------------------------
这要把class文件放到指定的目录下的,这些类只能存在于自己定义的classloader的classpath里且不能存在于父classloader的classpath里,也就是让父加载器找不到指定的类,这样才会让自定义的类加载器去加载类
------解决方案--------------------------------------------------------