JVM 内存区域和类的加载
内存区域
线程私有的空间有:
- 程序计数器
- 虚拟机栈
- 本地方法栈
线程共享的空间有:
- 堆
- 方法区
- 直接内存
注: 在 Java 1.8 后位于直接内存中的元空间替换了方法区。
在堆内存中又分为:
- 新生代
- 老年代
- 永久代(在 Java 1.8 后被元空间所取代)
类的加载
类从被加载到虚拟机内存中刚开始到卸载出内存为止总共需要经过以下几个阶段。
- 加载(Loading)
- 验证(Verification)
- 准备(Preparation)
- 解析(Resolution)
- 初始化(Initialization)
- 使用(Using)
- 卸载(UnLoading)
加载
加载阶段虚拟机做了下面三件事:
- 通过一个类的全限定名获取定义此类的二进制字节流。
- 将这个字节流所代表的的静态存储结构转化为方法区(元空间)运行时的数据结构。
- 在内存中生成一个代表这个类的
java.lang.Class
对象,作为方法区这个类的各种数据的访问入口。
链接
在链接的过程中需要完成验证,准备,解析三个步骤
验证
确保字节流中的信息符合虚拟机的要求,保证类的加载不会危害虚拟机自身安全。
在具体实现时采用了以下四种检验动作:
- 文件格式检验
- 元数据验证
- 字节码验证
- 符号引用验证
准备
在此阶段中会为类变量分配内存并且设置该类变量的默认初始值。
注:在准备阶段不会为 final 修饰的类变量分配内存并赋值。因为 final 在编译的时候就已经分配了相应空间,在准备阶段仅会完成显式初始化。
解析
虚拟机将常量池内的符号引用转化为直接引用。
初始化
初始化阶段是执行类构造器 <clinit>()
方法的过程。
注:clinit 方法是编译器将类变量与静态代码块的语句合并生成的,合并的顺序依照源文件中的位置决定。
JVM 内存区域和类的加载
https://wangqian0306.github.io/2020/jvm-class-loading/