图片很大,点击图片不知道能不能放大
定义
加载:将class里的静态二进制存储结构转化为内存中的的运行时数据结构,并且在方法区中生成class对象作为访问类数据的入口
链接.验证:校验文件是否符合格式,类型是否正确(是否继承了final修饰的类),字节码是否正确,符号引用验证(是否能找到对应类。)
链接.准备:为类变量在方法区中分配内存并分配初始值,是类变量不是实例变量。准备阶段不执行指令,初始值为0,例如定义了private static int a = 1;这里a准备阶段的值是0,到了初始化的阶段才会执行指令变成1,如果是引用类型则是null。而如果这个类变量是常量,final修饰,则在这个阶段就会初始化为他的值,如private static final int a =1; a就是1
链接.解析:解析是将常量池内的符号引用变成直接引用的过程。符号引用是一个可以找对应内存位置的字面量,直接引用是可以直接定位到内存地址与内存布局相关的引用。
对同一个符号引用进行解析是常见的事情,所以虚拟机会对解析进行缓存。
解析
解析类过程图如上,流程如下
解析字段过程如下,假设获取的字段是类C的字段
如果父类和接口有同名字段,会编译不通过
接口方法解析,类方法解析都类似
初始化
初始化阶段是真正开始执行字节码的阶段
初始化阶段是执行类构造器<clinit>的过程
初始化不用显示的调用父类构造器(构造函数需要),他会保证在子类clinit执行前父类的clinit已经执行完毕,所以第一个加载的类一定是Object
因为父类的clinit限制性,所以子类拿到的值一定是父类静态代码块执行后的值。
如果类没有静态代码块,那么这个类没有clinit方法
接口中不能有静态代码块,但是有clinit方法,执行前不需要先执行父接口的clinit
虚拟机会保证一个类的clinit被正确的加锁同步,如果多个线程去同时初始化一个类那么只会有一个线程去执行,其他都要阻塞等待,如果这个clinit耗时较长,就可能导致多个进程阻塞
使用和卸载
告辞没什么好说的