JVM 系列笔记目录
- 虚拟机的根底概念
- class 文件构造
- class 文件加载过程
- jvm 内存模型
- JVM 罕用指令
- GC 与调优
GC 基础知识
-
什么是垃圾
没有任何援用指向的一个对象或多个对象(循环援用)
-
如何找到垃圾
- 援用计数(ReferenceCount),毛病:无奈解决循环援用
- 根可达算法(RootSearching),从根开始查找,找到对象是有用的,找不到的对象为垃圾。
什么是根?留神联合上一篇博客 JVM 系列【5】JVM 罕用指令 - 运行时数据区进行了解。
- 线程栈变量 JVM Stack、native method stack
- 动态变量 static refercences in method area、Clazz
- 常量池 runtime cosntant pool
- JNI 指针 c/c++ 指针
-
常见的垃圾回收算法
- 标记革除(mark sweep)
毛病:地位不间断,产生碎片,效率偏低(须要进行两遍扫描)
实用状况:算法绝对简略,实用于存活对象比拟多的状况
- 拷贝算法 (copying)
阐明:没有碎片,节约空间,复制挪动对象,须要调整对象援用
实用状况:实用于存活对象较少的状况 只扫描一次
- 标记压缩(mark compact)
阐明:没有碎片,效率偏低(两遍扫描,指针须要调整)
- 标记革除(mark sweep)
-
JVM 堆内存分代模型(用于分代垃圾回收算法)
堆内存分代模型是局部垃圾回收器应用的模型,除 Epsilon ZGC Shenandoah 之外的 GC 都应用逻辑分代模型,然而 G1 是逻辑分代 物理不分代,除此之外都是逻辑分代 而且物理分代。
分代模型中,分新生代和老年代,比例是 1:2
- 新生代 = Eden 区 + 2 个 survivor 区
YGC 回收后,大多数的对象会被回收,活着的进入 s0;
再次 YGC,活着的对象 eden+s0 进入 s1;
再次 YGC,活着的对象 eden+s1 进入 s0;
年龄足够进入老年代,个别垃圾回收器是 15,CMS 是 6;为什么个别垃圾回收器分代年龄是 15?参考下 JVM 系列【4】内存模型 - 对象头的内容有哪些,对象头中 4 位标识 GC 年龄,所以最大的年龄是
2^4 -1 = 15
;s 区装不下,间接进入老年代。
- 老年代:寄存一些 ” 固执对象 ”,老年代满了或是调配不下了会触发 FCG。
- 永恒代(Permanent Generation,JDK1.7 以前)/ 元数据区(MetaSpace,JDK1.8 当前):寄存的是 Class 文件构造,永恒代必须指定大小限度,元数据能够设置也能够不设置,无下限(受限于物理内存),字符串常量在 1.7 以前寄存在永恒代,1.8 当前寄存在堆中。
- 新生代 = Eden 区 + 2 个 survivor 区
-
垃圾回收类型和对象调配过程
- 垃圾回收类型
上一个点解释了堆内存分代模型,这里对立下概念:MinorGC=YGC 指的是新生代即 Y 区的垃圾回收,MajorGC=FGC 指的是老年代调配不下或是满了产生的 GC,包含新生代和老年代。
- 对象如何调配
在之前的博客中 JVM 系列【4】内存模型 -new Object()面试 6 连问 - 对象如何调配,简略提过这一点。
- 垃圾回收类型
对照流程图,调配过程:
> 1. new 对象后优先在栈上调配,栈上调配的对象 `pop` 后就隐没;> 2. 是否是大对象(Y 区调配不下的对象)?是就调配到 O 区,O 区产生 FGC 后回收
> 3. 不是大对象,优先调配 TLAB(Thread Local Allocation Buffer 线程本地调配缓存)上,调配不下就调配到 Eden 区。
-
理解栈上调配、TLAB、调配担保机制和升代
- 哪些对象栈上调配?
线程公有对象、无逃逸对象即来到代码块就没有援用的对象、反对标量替换的对象,如类中变量能够用根本变量替换。
- 线程本地调配 Thread Local Allocation Buffer
独占 eden 空间,默认 1%;多线程时候不必竞争 eden 就能够申请空间,提高效率;可调配小对象 - 调配担保机制
在新生代无奈分配内存的时候,把新生代的对象转移到老生代,而后把新对象放入凌空的新生代。参考
- 对象何时进入老年代?
超过 MaxTenuringThreshold 指定的次数;
依据动静年龄计算进入老年代,Survivor 空间中年龄从小到大的对象进行累加,当退出某个年龄段后,累加和超过 survivor 区域 *TargetSurvivorRatio(默认 50%)的时候,就从这个年龄段往上的年龄的对象进行降职到老年代。参考
- 哪些对象栈上调配?
-
常见的垃圾回收器
常见的垃圾回收器有 Serial/SerialOld、ParallelScavenge/ParallelOld、ParNew/CMS、G1、ZGC、Shenandoah、Epsilon。Serial/SerialOld、ParallelScavenge/ParallelOld、ParNew/CMS 是分代的垃圾回收器,G1 是逻辑上分代物理上不分代,ZGC 和 Shenandoah 是不分代,Epsilon 是 JDK 调试用的垃圾回收器。
历史:JDK 诞生,Serial 追寻,为了提供效率诞生 PS, 为配合 CMS,诞生 PN,CMS 是 1.4 前期引入的,CMS 是里程碑式的 GC, 然而 CMS 故障比拟多,因而目前没有任何一个 JDK 版本默认 CMS。
-
Serial
年老代 串行回收
-
SerialOld
老年代 串行回收
-
PS(ParallelScavenge)
年老代 并行回收
-
PO(ParallelOld)
老年代 并行回收
-
PN(ParNew)
年老代 增强版 PS 配合 CMS 的并行回收。PN 和 PS 区别?PN 响应工夫优先;PS 吞吐量优先
-
CMS(ConcurrentMarkSweep)
老年代并发的, 垃圾回收和应用程序同时运行,升高 STW 的工夫(200ms);
CMS 问题比拟多,所以当初没有一个版本默认是 CMS,只能手工指定;
CMS 既然是 MarkSweep,就肯定会有碎片化的问题,碎片达到肯定水平,CMS 的老年代调配对象调配不下的时候,应用 SerialOld 进行老年代回收,STW 无法忍受;
- 如何解决碎片化:设定
-XX:+UseCMSCompactAtFullCollection
默认开启;设定-XX:CMSFullGCsBeforeCompaction
,默认为 0 指通过多少次 FGC 才进行压缩。 - 浮动垃圾问题解决?升高触发 CMS 的阈值,放弃老年代有足够的空间;参数
-XX:CMSInitiatingOccupancyFraction
指定应用 CMS 时老年代应用了指定阈值的内存后触发 FGC,倡议 68-92%
应用的算法:三色标记 +Increamental Update
- 如何解决碎片化:设定
-
G1
STW 能够达到 10ms
算法:三色标记 +SATB
-
ZGC
STW 号称能够达到 1ms
算法:色彩指针 ColoredPointers + LoadBarrier
-
Shenandaoh
算法:ColoredPointers + WriteBarrier
-
-
垃圾回收器和内存大小的关系
Serial 几十兆
PS 上百兆 - 几个 G
CMS 20G 左右
G1 上百 G
ZGC 4T-16T(JDK13 能够反对)
常识分享,转载请注明出处。学无先后,达者为先!