类加载

2020-01-30  本文已影响0人  Audience0
image.png

类加载子系统:
在Java虚拟机中,负责查找并装载类的部分称为类加载子系统,类加载子系统用于定位和加载编译后的class文件


类加载的生命周期:
类从被加载到虚拟机内存中开始,到卸载出内存位置,她的整个生命周期包括:加载,验证,准备,解析,初始化,使用和卸载7个阶段


image.png

1.加载
首先,加载是 类加载的一个阶段,注意不要混淆.
在加载阶段,虚拟机需要完成以下3件事情
1)通过一个类的全限定名来获取定义此类的二进制字节流
此处并没有指定字节流的来源,所以,可以是从JAR,WAR或者从网络,运行时计算生成(动态代理)都可以
2)将这个字节流所代表的静态存储结构化为方法区的运行时数据结构
方法区:用于存储已被虚拟机加载的类信息,常量,静态变量
3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口

2.验证
验证是连接阶段的第一步,目的是为了确保Class文件字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全.
1)文件格式验证
是否以魔数0xCAFEBABE开头
主次版本号是否在当前虚拟机处理范围之内
.....
2)元数据验证
对字节码描述信息进行语义分析即验证class文件的Java语法是否正确
这个类是否有父类(除了Object,其他的类都有父类)
这个类是否继承了不可以被继承的类(被final修饰的类)
这个类如果不是抽象类,则是否实现了所有父类要求必须实现的方法
类中的字段,方法是否与父类产生矛盾(例如覆盖了父类final修饰的字段)
......
3)字节码验证
保证方法体中类型转换是有效的,例如是否把一个类赋值给一个不相关的类型上
......
4)符号引用验证
符号引用中通过字符串描述的全限定名是否能找到对应的类
符号引用中的类,字段,方法的访问性(public,private,protected,default)是否可以被当前类访问
......

3.准备 --- 为类变量分配内存并初始化
准备阶段是连接阶段的第二阶段,该阶段是正式为 类变量 分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配.
需注意:
1)此处的内存分配和初始化都是针对于类变量.
2)此处所谓的初始化是初步的(通常情况),并非真正的初始化.
例如
public static int value = 123;
经过准备阶段之后,value的初始值是0,而不是123.因为这时候尚未开始执行任何Java方法,而把value赋值为123的putstatic指定是程序被编译后,存放在类构造器<clinit>()方法之中,所以把value赋值为123是在初始化阶段才会执行的
3)也有一些特殊情况,如果定义的是常量,如下, 则在准备阶段就会初始化为123
public static final int value = 123;

4.解析
解析阶段是虚拟机将常量池内的符号替换为直接引用的过程

直接引用:
直接引用可以是直接指定目标的指针,相对偏移量或者是一个间接定位到目标的句柄.

1)类或接口解析
2)字段解析
3)类方法解析
4)接口方法解析

5.初始化
类初始化阶段是加载过程的最后一步.到了初始化阶段,才真正开始执行类中定义的Java程序代码
在准备阶段,变量已经赋过一次系统要求的初始值,而在初始化阶段,则根据程序员通过程序制定的主观计划去初始化类变量和其他资源,或者可以从另外一个角度来表达:初始化阶段是执行类构造器方法的过程.


类加载器

通过一个类的全限定名来获取描述此类的二进制字节流;
类加载器主要实现类的加载;

image.png

Bootstrap ClassLoader启动类加载器(C++ 实现,是虚拟机的一部分);
Extension ClassLoader 扩展类加载器(Java 实现,独立于虚拟机外部且全继承自 java.lang.ClassLoader)
Application ClassLoader 应用程序加载器(Java实现)
Custom ClassLoader 自定义类加载器(java实现,用户自己定义的)
除了顶层的启动类加载器之外,其他类加载器都有自己的父类加载器;

双亲委派模型:
如果一个类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的家在请求最终都传到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求时,子加载器才会去尝试自己去加载

双亲委派的好处:
Java类随着它的加载器一起具备了一种带有优先级层次关系.
例如Java.lang.Object,它存放在rt.jar之中,无论哪一个类加载器要加载这个类,最终都是委派给最顶层的Bootsrap ClassLoader去加载.保证了Object这个类加载出来都是同一个类(类与类比较,是建立在同一个加载器的基础上的)

上一篇下一篇

猜你喜欢

热点阅读