转载请注明来自:http://chillwarmoon.iteye.com
在一个ClassLoader实例中,如果加载某个Class,那么被加载的Class是属于该ClassLoader所定义的namespace之内的。表现为不同的classloader实例虽然加载的Class完全相同,但是不能够相互类型转化,而且不能够通过类型转换成其他classloader加载的类。
但是在自定义的CustomClassLoader中,(1)Test test=(Test)clazz.newInstance()的类型转换是成功的,而且转换的是SystemClassLoader所加载的Test.class;(2)TestSub test2=(TestSub)clazz.newInstance()的类型转换是失败的。
这是为什么呢?
答案就在于CustomClassLoader并未覆盖父类的loadClass方法,在该例子中,虽然是通过CustomClassLoader.load方法,来调用defineClass方法加载class,但是该defineClass方法仍然需要调用ClassLoader.loadClass方法来级联加载与之相关的类,包含其父类,接口。因此该例子中仅仅是对字节码文件TestSub.class进行了load,而Test仍然是由SystemClassLoader所加载,因此会出现Test test=(Test)clazz.newInstance()成功执行,而TestSub test2=(TestSub)clazz.newInstance()执行失败的情况。
如果将CustomClassLoader.load方法名称改变为loadClass,则在调用defineClass时会加载Test.class到该classLoader实例,此时再次调用Test test=(Test)clazz.newInstance()会产生类型转换失败的错误。
PS:在调用clazz.newInstance方法时,会使用classLoader的loadClass方法,来加载类的关联类。因此不同的classLoader都有着自己的namespace。
在一个ClassLoader实例中,如果加载某个Class,那么被加载的Class是属于该ClassLoader所定义的namespace之内的。表现为不同的classloader实例虽然加载的Class完全相同,但是不能够相互类型转化,而且不能够通过类型转换成其他classloader加载的类。
但是在自定义的CustomClassLoader中,(1)Test test=(Test)clazz.newInstance()的类型转换是成功的,而且转换的是SystemClassLoader所加载的Test.class;(2)TestSub test2=(TestSub)clazz.newInstance()的类型转换是失败的。
这是为什么呢?
public class CustomClassLoader extends ClassLoader{
public Class load(String arg){
return getClass(arg);
}
public Class getClass(String arg){
String path=System.getProperty("user.dir");
String fullPath=path+"/bin/"+arg.replace(".", File.separator)+".class";
byte[] classCode=null;
File f=new File(fullPath);
if(f.exists()){
try {
FileInputStream fis=new FileInputStream(f);
classCode=new byte[fis.available()];
fis.read(classCode);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return defineClass(arg,classCode, 0, classCode.length);
}
try {
return findSystemClass(arg);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static void main(String args[]){
Class clazz=new CustomClassLoader().load("com.hzb.classloader.TestSub");
try {
Test test=(Test)clazz.newInstance();
TestSub test2=(TestSub)clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
答案就在于CustomClassLoader并未覆盖父类的loadClass方法,在该例子中,虽然是通过CustomClassLoader.load方法,来调用defineClass方法加载class,但是该defineClass方法仍然需要调用ClassLoader.loadClass方法来级联加载与之相关的类,包含其父类,接口。因此该例子中仅仅是对字节码文件TestSub.class进行了load,而Test仍然是由SystemClassLoader所加载,因此会出现Test test=(Test)clazz.newInstance()成功执行,而TestSub test2=(TestSub)clazz.newInstance()执行失败的情况。
如果将CustomClassLoader.load方法名称改变为loadClass,则在调用defineClass时会加载Test.class到该classLoader实例,此时再次调用Test test=(Test)clazz.newInstance()会产生类型转换失败的错误。
PS:在调用clazz.newInstance方法时,会使用classLoader的loadClass方法,来加载类的关联类。因此不同的classLoader都有着自己的namespace。