jvm 组件
1.栈
1.1. 虚拟机栈
虚拟机栈是java执行方法的场所,在执行方法时会创建多个栈帧用来存储数据和部分过程结果,以及临时变量,操作数栈,动态链接,方法出口, 本地变量表等,生命周期随着方法创建而创建,结束而销毁
1.2. 本地方法栈
用于执行内部的native方法
2.堆
2.1.堆内存
可通过-xms(堆起始内存)和-xmx(堆最大内存)控制堆的所占空间,一般会配置相同的值, 是为了java垃圾回收之后不需要重新分隔计算堆区大小,从而提升性能
①存放对象和数组(栈中只会保存对象和数组的地址引用), 线程共享, 用来存储类的实例,
②内置gc垃圾回收机制
③堆内存可以在物理上是不连续的,但是在逻辑上是连续的
④一个进程中只存在一个堆
⑤堆中还划分线程**私有缓存区**提供给单个线程
2.2.方法区(常量池在方法区内)
- jdk8之后方法区在堆的元空间中,
- 方法区主要存储类信息, 即时编译器编译的代码, 常量, 静态变量
2.3.gc垃圾回收机制
构成:
①jdk1.8之前: 新生代(eden+surviver from+surviver to),老年代,永久代
②jdk1.8及之后:新生代,老年代,元空间(本地内存)
gc回收方式:
①MinorGC: 新生代GC,用来回收Eden和survivor区,survivor区会在垃圾回收n次之后进入老年代,n默认配置为15,可调节
②MajorGC: 老年代GC, 用来回收老年代,老年代
③FullGC: 整堆回收
gc回收策略:
- Eden区满了会触发MinorGC, Minor会触发stw, stw状态下, 处理GC线程,其他线程都不能执行
- MajorGC速度比MinorGC更慢, 10倍以上, stw也更长, MajorGC后内存也不够,会报OOM
- FullGC触发机制
①使用system.gc()时, 系统会建议使用FullGC
②方法区空间不足
③老年代空间不足
④老年代可用对象空间不足以装下新存入对象
3.其他
3.1.程序计数器
程序计数器时线程私有的, 用于记录线程的执行位置, 在线程存活,执行,等待,休眠,死亡时触发程序计数器来查找位置
4. 一个类的初始化完整流程
类的加载:
①加载: 将字节码文件通过io流的方式读取到jvm的方法区, 并且在堆中生成Class对象
②**链接: **
**验证:验证字节码的正确性, **
**准备:为类的静态变量分配内存,并初始化默认值 **
解析: 将类的符号引用替换为直接引用
③初始化: 执行静态代码
4.1. 测试方法执行
- 类在java中加载需要先编译成.class文件, class文件存储在堆的方法区中
- main方法运行后, 会在栈中分配区域, 执行main方法
- 涉及到类时, 会先加载父类和父接口, 静态变量和常量进入方法区, 静态变量法如果没被赋值, 会被赋予默认初始值, 类中如有静态代码块, 会在方法区分出一个栈帧来运行静态代码块
- 创建对象时, 根据方法区中类的信息创建一个对象或数组, 对象和数组存储在堆中, 对象和数组的引用存储在了栈
- 执行方法时, 在栈中生成一个栈帧, 在栈中存储方法信息(返回值,参数信息,方法出口等)
- 多线程下, 会触发程序计数器, 并在堆线程共享区域生成线程共享的对象, 堆中还有私有缓存区, 用于本线程私用对象和数组的存储