强引用:
弱引用:溢出前回收
软引用:第二次GC回收
虚引用:第一次GC直接回收(为了触发finalize())
方法区的内容
- 类型信息
- 常量
- 静态变量
- JIT代码缓存
- 运行时常量池=常量池表:编译器字面量,运行期添加 String.intern()
方法区的垃圾回收
- 废弃常量
- 不再使用的类型(java.lang.Class)
虚拟机要支持才行
JVM运行时数据区
- 程序计数器
- 虚拟机栈
- 本地方法栈
- 方法区(公有)
- 堆(公有)
直接内存:不是运行时数据区的一部分
直接内存:NIO, DirectByteBuffer
对象
创建
同一个线程内存分配方法
- 指针碰撞:直接向后偏移,碰撞后继续向后
- 空闲列表
不同线程分配内存
- 加锁
- TLAB:线程私有的分配缓冲区
结构
对象头(Header)
Mark Word(对象自身的运行时数据)
- 哈希码
- GC分代年龄
- 锁标志状态
- 线程持有的锁
- 偏向线程id
- 偏向时间戳
类型指针
- 指向类型元数据的指针
实例数据(Instance Data)
对齐填充(Padding)
任何对象的大小都是8字节的整数倍
访问定位
- 句柄
- 直接指针(Hotspot)
分代收集(Generational Collection) Partial GC
新生代(Minor GC)
老年代(Major GC)(CMS)
全GC(Full GC)
涉及部分区域引用的都是跨代引用问题
记忆集(Remember Set)
卡表(脏页)
更新
写屏障
全局性引用
根节点枚举必须暂停用户线程
全局性引用 执行上下文
安全点主动式终端-引用关系确认
CMS 增量更新
G1 Shenandoah 原始快照
老年代分配担保,所以老年代大小大于新生代大小
CMS(标记清除)其他标记整理
主内存
堆
工作内存
线程私有,如虚拟机栈
volatile的作用
synchronized锁升级
偏向锁:通过在对象头存储threadid,使用时判断id是不是当前threadid
轻量级锁(自旋锁CAS)
重量级锁
加锁需要切换用户态和内核态,消耗时间
锁消除:编译器确认该变量不会被多线程访问
锁粗化:频繁进入锁
双亲委派模型
Bootstarp
Ext
App
破坏双亲委派模型:线程上下文加载器(Thread Context ClassLoader)
父类加载器去请求子类加载器完成类加载的行为
虚拟机栈
栈帧(Stack Frame)结构
操作数栈(Operand Stack)
局部变量表(最小单位:变量槽Variable Slot 32位)
动态连接(Dynamic Linking)
返回地址
方法调用
解析
- 正常调用完成
- 异常调用完成
分派
动态分派
继承
静态分派
重载
类文件结构
常量池
访问标志
类索引、父类索引、接口索引集合
字段表集合
方法表集合
属性表集合(其中Code属性保存代码)
升级老年代
长期存活对象 > 15 次
大对象
相同年龄占一半以上 大于等于该年龄
触发Full GC时机
老年代连续空间 > 新生代对象总大小
G1
不是一次清理干净,比CMS占用高
停顿时间模型
回收集
Region 最小回收单元
Hurmongous 看作老年代
G1 10% - 20%内存用于回收新分配
TMAS默认不回收(用于回收时新分配对象)
Parallel Scavenge
配合Parallel Old(JDK6)
吞吐量(自适应垃圾调节)
线程数=(核心+3) / 4,所以低于4核心用(ParNew + CMS + Serial Old)
低延迟垃圾收集器
内存占用 吞吐量 低延迟
Shenandoah
低延迟
连接矩阵
转发指针
CAS 并发准确性
拦截引用
ZGC
Region 动态创建和销毁
染色指针
指针46位中高4位存标志
转发表 自愈
可达性分析的根节点
虚拟机栈
方法区:类静态属性 常量
本地方法栈
虚拟机内部调用(Class对象)
同步锁
JMXBean JVMTI