27 类的生命周期
Posted cathy_mu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了27 类的生命周期相关的知识,希望对你有一定的参考价值。
jvm是不会读.java文件的,需要编译成.class文件才行
加载
- 通过全类名获取此类的二进制字节流
- 将字节流所代表的静态存储结构转换成方法区的运行时数据结构
- 在内存中生成一个class对象,作为方法区这些数据的访问入口
数组类型是由java虚拟机直接创建的,不是通过类加载器创建的。
非数组类型可以通过自定义类加载器完成加载。(重写loadclass方法)连接
加载阶段未结束,连接阶段可能已经开始了。
验证
文件格式验证
验证字节流是否符合class文件格式规范- 是否以0xCAFEBABE开头
- 主次版本号是否在当前虚拟机处理范围之内
- 常量池中的常量是否有不被支持的类型
元数据验证
对字节码的信息进行语义分析,保证描述的信息符合java
语言规范- 类是否有父类
- 是否继承了不能被继承的类(被final修饰的类)
字节码验证
- 验证程序语义合法
- 符号引用验证
准备
为类变量(即静态变量)分配内存并设置变量初始值。
在1.7前放在永久代方法区,1.7后字符串常量池、静态变量移动到堆中。
这里的初始值是数据类型对应的0值。如果被final修饰了,则被赋值为实际值。解析
将常量池内的“符号引用”替换为“直接引用”。
针对类、接口、类方法、接口方法、方法类型、方法句柄、和调用限定符。
直接引用是指向目标的指针、相对偏移量或可间接定位到目标的句柄。每个类有一张方法表存放类中所有方法,只要知道某方法在表中偏移量就可以直接调用。
初始化
这一步jvm开始真正执行类中定义的java程序代码。
执行<clinit>方法,带锁线程安全,可能引起阻塞。
以下五种情况,必须对类进行初始化- new、getstatic、putstatic、invokestatic指令,分别是创建实例、访问静态变量、给静态变量赋值、调用类静态方法。
- 使用java.lang.reflect包对类进行反射调用时,例如class.forname(""),newInstance()
- 初始化类时,如果父类没初始化,要先初始化父类
- 虚拟机启动时,会先初始化main方法所在的类
- 要使用轻量级的反射调用methodHandle、VarHandle,必须先使用findStaticVarHandle初始化类
- 如果接口定义了jdk8新加入的默认方法(被default修饰的方法),初始化这个接口的实现类之前要先初始化接口。
使用
卸载
卸载即class对象被gc,需要满足三个要求
- 所有实例对象都被gc了。
- 类没有被任何地方引用。
- 类加载器实例被gc。
由jvm自带的类加载器加载的类是不会被卸载的,由我们自定义的类加载器加载的类是可能被卸载的。
以上是关于27 类的生命周期的主要内容,如果未能解决你的问题,请参考以下文章