1:类加载
(1)加载:
1.根据类的全限定名去获取类的二进制字节流。
2.把静态存储结构加载到方法区的运行时数据区。
3.在堆中创建一个java.lang.Class作为方法区的访问入口
(2)校验
1.文件格式校验:魔数是否以cafebady开头;版本是否符合虚拟机要求超出虚拟机范围;
2.元数据校验:类是否有父类(除了object类);父类是否有被finl修饰;除了虚拟类是否都实现了父类接口
3.字节码校验:在操作数栈加载int类型的变量,但却把他当作long类型放在本地变量表,把一个父类赋值给一个子类
4.符号引用校验:根据符合是否能找到相应类
(3)准备:给静态变量分配内存空间并赋0值
(4)解析:把符号引用换成直接引用
(5)初始化
初始化必须先加载 校验 准备
1.出现new。
2.访问静态属性(除finl)
3.访问静态方法
如果父类没有初始化必须先初始化父类
(6)卸载
2:类加载器
(1)bootstrap class loader:启动类加载器 加载lib/包下
(2)extension class loader:扩展类加载器 加载lib/ext/包下
(3)application class loader:应用程序类加载器 在这class path
双亲委派模式:当加载一个类的时候首先会询问他的父类加载器,这里的父类不是继承关系而是合作公用一段程序 ,来加载,只有父类加载器不能加载的时候才自己加载;优点是安全节省代码,避免有些类比如自己写object 被加载;
双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。这里类加载器之间的父子关系一般不会以继承(Inheritance)的关系来实现,而是都使用组合(Composition)关系来复用父加载器的代码。
使用双亲委派模型来组织类加载器之间的关系,有一个显而易见的好处就是 Java 类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类 java.lang.Object,它存放在 rt.jar 之中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此 Object 类在 程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个称为 java.lang.Object 的类,并放在程序的 ClassPath 中,那系统中将会出现多个不同的 Object 类,Java 类型体系中最基础的行为也就无法保证,应用程序也将 会变得一片混乱。
破坏双亲委派模式:
1.tomcat:隔离,web app类加载器和jsp类加载器采用隔离的方式加载一个项目的不同版本
2.jdbc(spi):statement 类按理书应该有启动类加载器价值,但他的实现缺在不同服务商的jia报是有application类加载器加载