------------------------------------------------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