共计 1027 个字符,预计需要花费 3 分钟才能阅读完成。
加载
- 通过全类名获取此类的二进制字节流
- 将字节流所代表的动态存储构造转换成办法区的运行时数据结构
- 在内存中生成一个 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 自带的类加载器加载的类是不会被卸载的,由咱们自定义的类加载器加载的类是可能被卸载的。
正文完