JVM主要由三块组成:
- 类加载子系统
- 运行时数据区
- 字节码执行引擎
一、类加载子系统
参考 类加载机制
二、运行时数据区
1.程序计数器
跟随线程,记录当前线程指令执行位置
唯一不会发生OOM的区域
2.虚拟机栈(默认1M)
跟随线程,调用方法一个一个栈帧入栈(注意OOM和StackOverflowError的区别)
栈帧入栈出栈也可看出来局部变量的有效区域
每个栈帧包括:
本地变量表:方法内的变量
操作数栈(栈结构):操作数据的临时存放区
动态链接:符号引用转直接引用
方法出口:方法结束回到调用方的指定位置
3.本地方法栈
native方法相关
4.堆
存放大部分的对象
1年轻代:
8Eden
1s0
1s1
2老年代
minor gc
full gc
STW:stop the world
5.方法区(元空间)(自动扩容机制)
常量
静态变量
类元信息
默认21M,方法区最好设置MetaSpaceSize和MaxMetaSpaceSize,减少不必要的full gc
三、字节码执行引擎
随着程序运行修改程序计数器
====================
对象:
对象在内存包括:对象头、实例数据、对齐填充
对象的创建:
1.类加载检查
2.分配内存
指针碰撞
空闲列表
分配争抢解决方法:CAS、TLAB
对象内存分配判断流程:栈上分配(逃逸分析、标量替换)?大对象(怎样算大对象)?TLAB?eden
对象动态年龄判断机制:年龄1+年龄2+…+年龄n>Survivor的50%,就把年龄n及以上的对象放入老年代
老年代空间分配担保机制:老年代剩余可用空间old_available,年轻代里现有的所有对象(包括垃圾对象)young_hold,历次minor_gc进入老年代的对象的平均大小ave_minor_to_old。
//老年代空间分配担保机制伪代码
if(old_available >= young_hold){
minor gc;
} else {
if(-XX HandlerPromotionFailure){
if(old_available >= ave_minor_to_old){
minor gc;
} else {
full gc;
}
} else {
full gc;
}
}
3.初始化
成员变量设置初始值
4.设置对象头
锁状态
锁标记
分代年龄
Klass Pointer类型指针(类元数据的指针)
对象回收
引用计数法
存在循环引用问题
可达性分析法
GC Root
引用类型
强、软、弱、虚
finalize
对象回收之前先判断是否有必要执行finalize()方法,在finalize()方法内是最后复活机会,finalize()只会执行一次。
如何判断一个类是无用的类
- 该类的所有对象都被回收
- 加载该类的ClassLoader已经被回收
- 该类的Class对象没有在任何地方引用,不能通过反射访问该类