JVM

强引用:
弱引用:溢出前回收
软引用:第二次GC回收
虚引用:第一次GC直接回收(为了触发finalize())

方法区的内容

  1. 类型信息
  2. 常量
  3. 静态变量
  4. JIT代码缓存
  5. 运行时常量池=常量池表:编译器字面量,运行期添加 String.intern()

方法区的垃圾回收

  1. 废弃常量
  2. 不再使用的类型(java.lang.Class)
    虚拟机要支持才行

JVM运行时数据区

  1. 程序计数器
  2. 虚拟机栈
  3. 本地方法栈
  4. 方法区(公有)
  5. 堆(公有)
    直接内存:不是运行时数据区的一部分
    直接内存:NIO, DirectByteBuffer

对象

创建

同一个线程内存分配方法

  1. 指针碰撞:直接向后偏移,碰撞后继续向后
  2. 空闲列表

不同线程分配内存

  1. 加锁
  2. TLAB:线程私有的分配缓冲区

结构

对象头(Header)

Mark Word(对象自身的运行时数据)
  1. 哈希码
  2. GC分代年龄
  3. 锁标志状态
  4. 线程持有的锁
  5. 偏向线程id
  6. 偏向时间戳
类型指针
  1. 指向类型元数据的指针

实例数据(Instance Data)

对齐填充(Padding)

任何对象的大小都是8字节的整数倍

访问定位

  1. 句柄
  2. 直接指针(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)
返回地址

方法调用

解析

  1. 正常调用完成
  2. 异常调用完成

分派

动态分派
继承
静态分派
重载

类文件结构

常量池
访问标志
类索引、父类索引、接口索引集合
字段表集合
方法表集合
属性表集合(其中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

上一篇:JVM增强


下一篇:走进JVM(二)——内存模型与垃圾回收