`
chillwarmoon
  • 浏览: 155889 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

ClassLoader对类的级联加载

    博客分类:
  • JVM
阅读更多
转载请注明来自: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()的类型转换是失败的。
这是为什么呢?
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。
分享到:
评论

相关推荐

    java面试题(整理)

    - **Application ClassLoader**:加载应用程序类。 12. **面向对象的思想描述手中的笔** - **类**:`Pen` - **对象**:具体的笔实例。 - **属性**:颜色、型号等。 - **方法**:写字、画画等行为。 13. **...

    Spring.3.x企业应用开发实战(完整版).part2

    3.2.2 类装载器ClassLoader 3.2.3 Java反射机制 3.3 资源访问利器 3.3.1 资源抽象接口 3.3.2 资源加载 3.4 BeanFactory和ApplicationContext 3.4.1 BeanFactory介绍 3.4.2 ApplicationContext介绍 3.4.3 父子容器 ...

    Spring3.x企业应用开发实战(完整版) part1

    3.2.2 类装载器ClassLoader 3.2.3 Java反射机制 3.3 资源访问利器 3.3.1 资源抽象接口 3.3.2 资源加载 3.4 BeanFactory和ApplicationContext 3.4.1 BeanFactory介绍 3.4.2 ApplicationContext介绍 3.4.3 父子容器 ...

    Spring_3.x企业应用开发实战 目录

    - **类装载器ClassLoader**:了解类装载机制。 - **Java反射机制**:利用反射机制动态创建和访问对象。 - **3.3 资源访问利器** - **资源抽象接口**:Spring 提供的资源访问接口。 - **资源加载**:加载各种...

    JAVA核心知识点整理(有效)

    1. 目录 1. 2. 目录 .........................................................................................................................................................1 JVM ........................

Global site tag (gtag.js) - Google Analytics