日期:2014-05-20  浏览次数:20779 次

自定义classloader问题。
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里,也就是让父加载器找不到指定的类,这样才会让自定义的类加载器去加载类

探讨

引用:
public static final void loadJarFile(File file) {
try {
addURL.invoke(system, new Object[] { file.toURI().toURL() });
// System.out.println("load_jar_package:" + file.getAbsolutePath……

------解决方案--------------------