黑马程序员_类加载器知识总结



------------------------------------------------android培训java培训期待与您交流!-----------------------------------------------

类加载器的作用

把存放在硬盘里面类的字节码加载到内存里面来,然后再对其进行处理

类加载器本质

它也是Java类,第一个类加载器不是java类,是BootStrap(它是由C++写的一段程序)。

类加载器原理

因为类加载器采用的是委托机制,委托机制的原理就是,
当某一个类的字节码要加载到内存来的时候,首先让最
上级的那个类加载器来加载,如果说最上级类加载器没
有加载到该类的字节码那么就让下一级类加载器对其进
行加载也就是说如果所有祖宗类加载器都没有加载到类,
回到发起者类加载器,还加载不了,那么抛ClassNotFoundException

 


由图可知在比方说加载CLASSPATH指定的所有jar或目录里面的类的时候,
首先找BootStrap从JRE/lib/rt.jar目录下加载没有找到该类再交给
ExtClassLoader从JRE/lib/ext/*.jar目录下加载,还没有加载到类,
那么就再交给发起者类加载器AppClassLoader从CLASSPATH指定的所有
jar或目录里面加载对应的类,没有加载到得话就报错

 

出现的问题:

①为什么每个类加载器加载类时,要先委托给其上级类加载器

因为为了集中管理,如果交给其他的类加载器,比方说A类加载器在加载
Systemt时加载到了一个system,B类加载器加载Systemt时加载也加载到了
一个system那么内存中就出现了两份字节码,会出现多份字节码重复的现象

②如果自己写一个system类会不会被加载

通常不可以因为委托机制BootStrap首先就从rt.jar包中加载到了system
根本就不会加载自己写的那个system,如果硬要找自己的system可以自己
写一个类加载器并且撇开委托加载机制

编写自己的类加载的方法(用的伪代码实现)

①首先定义一个类继承ClassLoader,并且重写其findClass方法

public class MyClassLoader extends ClassLoader
	{

		public MyClassLoader()
		{
		}

		public MyClassLoader(String classDir)
		{
			this.classDir = classDir;
		}

		@Override
		protected Class<?> findClass(String name)
		{
			// 这里根据name然后理由流操作从磁盘中读取文件然后对其进行操作
			// 之后得到其文件的字节信息最后用defineClass得到该类的字节码
			// byte[] bytes = bos.toByteArray();
			// return defineClass(bytes, 0, bytes.length);
		}
	}

②其次写一个要被自己写的类加载器加载的类

public class ClassLoaderAttachment extends Date
	{
		public String toString()
		{
			return "helloworld";
		}
	}


③最后写一个测试类

Class clazz = new MyClassLoader("mylib").loadClass("ClassLoaderAttachment");

Date d1 =  (Date)clazz.newInstance();

由自己编写的类加载器引出的思考

①为什么上面的ClassLoaderAttachment要继承Date对象

因为Class clazz = new MyClassLoader("itcastlib").loadClas("ClassLoaderAttachment");
ClassLoaderAttachment d1 =  (ClassLoaderAttachment)clazz.newInstance();
编译器在调用第二句执行语句的时候,编译器会从自己的类加载器中加载该类,
而我们已经把相应类加载里面的字节码替换为自己加密了的字节码,所以编译器
无法解析我们自己加密了的字节码就会报错,而Date我们没有改变所以编译器可以解析

②模版方法在类加载器里面的运用

模版方法的特征:
ⓐ父类具有统一的操作步骤或操作过程
ⓑ子类实现具有不同的操作细节
ⓒ存在多个具有同样操作步骤的应用场景,但某些具体的操作细节却各不相同
而类加载器也是这样,子类加载器加载不同的类可能方法不同,但是总的流程都是一样的,子类加载器先找父类加载器加载相关的类,没有在找自己(细节)


//主类
public abstract class MakeCar {
	//组装车头
	public abstract void makeHead();
	//组装车身
	public abstract void makeBody();
	//组装车尾
	public abstract void makeTail();
	//把主题的流程已经给规定好了
	public void make() {
		this.makeHead();
		this.makeBody();
		this.makeTail();
	}
}
public class MakeJeep extends MakeCar {//子类继承父类,实现细节
	public void makeBody() {
		System.out.println("jeep:组装车身");
	}
	public void makeHead() {
		System.out.println("jeep:组装车头");
	}
	public void makeTail() {
		System.out.println("jeep:组装车尾");
	}

}
//测试类
public class MainClass {
	public static void main(String[] args) {
		MakeCar jeep = new MakeJeep();
		jeep.make();//只需调用父类的哪个固定封装好了的流程
	}
}

③Tomcat类加载器的高级问题分析总结

如果类加载器MyClassLoader负责加载A类,A类引用了B了类,而B类却不是放在MyClassLoader指定的目录下或者说不由MyClassLoader负责加载那么运行的时候就会报错,因为MyClassLoader加载A类的时候找不到类B。

----------------------------------------- android培训java培训、java学习型技术博客、期待与您交流! --------------------------


详情请查看:http://edu.csdn.net/heima
















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值