一 . GC基础
1.什么是垃圾
自动内存回收,编程简单,系统不容易出错,手动释放内存,容易出现两种类型问题:
- 忘记回收
- 多次回收
没有任何引用指向一个对象或者多个对象(循环引用)
2.如何定义垃圾
1.引用计算
2.根可达算法
3.常见的垃圾回收算法
- Mark-Sweep(标记清除)
- 位置不连续
- 产生碎片
清除标记过的垃圾
- Copying(复制算法)
- 没有碎片
- 浪费空间
把上面的要存活对象copy到下面第一行去,然后删除上面的数据
- Mark-Compact(标记压缩)
- 效率偏低
- 没有碎片
找到标记过垃圾后清除然后把后面存活移动对象移动过来
4.JVM内存分代模型(用于分代垃圾回收算法)
- new-young
存活对象少
使用copy算法,效率高 - old
垃圾少
一般用mark compact(标记压缩)
G1使用copy
部分垃圾回收使用模型
新生代+老年代+永久代(1.7)/元数据区(1.8) Metaspace
永久代/元数据区:Class
永久代必须指定大小限制
元数据可以设置,也可以不设置,无上限(受限于物理内存)
字符串常量: 1.7-永久代
1.8-堆
MethodArea逻辑概念:在1.7是永久代,1.8是元数据区
- MinorGC=YGC
- MajorGC=FGC
多数情况下FGC时同时执行YGC
-新生代-
新生代=Eden+两个survivor
1. YGC回收之后,大多数的对象会被回收,活着的进入s1
2. 再次YGC,活着的对象(eden+s1)会进入s2
3. 每次copy年龄加一,年龄达到一定数值(一般是15次,cms是6次,ZGC没有-因为不分代)进入老年代
4. s区装不下了也会进入老年代
-老年代-
1. 装 顽固分子
2. 老年代满了FGC
-调优的目标-
尽量避免(减少)FGC
5.Garbage Collectors
三个用于年轻代,三个用于老年代,三个没有区分
Seral 串行回收: (年轻代)
停下所有的用户线程,开始垃圾回收,回收完之后程序继续运行
Parallel Scavenge 并行回收
多个线程同时进行垃圾回收,效率比单线程要高一些
ParNew
新一代的垃圾并行回收
在Parallel Scavenge基础上设计的,为了配合CMS的并行回收
SerialOld
Serial放到old区(old版的)
ParallelOld
Parallel Scavenge放到old区(old版的)
CMS initial mark
CMS,全称Concurrent Mark and Sweep,用于对年老代进行回收,目标是尽量减少应用的暂停时间,减少full gc发生的机率,利用和应用程序线程并发的垃圾回收线程来标记清除年老代。CMS并非没有暂停,而是用两次短暂停来替代串行标记整理算法的长暂停。
内外的设置正常收集周期是这样的:
1)CMS-initial-mark 初始标记
2)CMS-concurrent-mark 并发标记的
3)CMS-concurrent-preclean 执行预清理 注: 相当于两次 concurrent-mark. 因为上一次c mark,太长.会有很多 changed object 出现.先干掉这波.到最好的 stop the world 的 remark 阶段,changed object 会少很多.
4)CMS-concurrent-abortable-preclean 执行可中止预清理
5)CMS-remark 重新标记
6)CMS-concurrent-sweep 并发清除
7)CMS-concurrent-reset 并发重设状态等待下次CMS的触发
其中,CMS-initial-mark和CMS-remark会stop-the-world。
三色标记 - 会出现错标 - Incremental Update(增量更新过程中也会产生错标) - 要有一个Remark
(写屏障)
ConcurrentMarkSweep(老年代,并发的垃圾回收和应用程序同时运行,(号称))降低STW时间到(200ms))
并发标记时比较慢但是可以和程序同时运行不会造成StopTheWrold
承上启下开始并发回收
G1(1ms)
三色标记+SATB
(写屏障)
解决了Incremental Update(增量更新)之后必须要Remark的
分区回收,优先清理垃圾最多的小块
物理上不分代 , 每个小区在逻辑上分代
G1也有STW和FGC
ZGC(oracle)(1ms) PK C++/Shenandoah(openJDK)现在是二选一的关系没确定用谁听说ZGC
ColoredPointers(颜色指针 着色指针)
(读屏障)
Shenandoah
ColoredPointers(颜色指针 着色指针)
(写屏障)
ZGC逻辑上物理上都没有分代的概念
能支持大概4T
不用调优,没有STW
Eplison
啥也不干
调试用,确认不用GC参与就能干完活
垃圾收集器跟内存大小的关系
- Serial 一般几十兆用
- PS 上百兆 -几个G用(如果太大会STW很久)
- CMS - 20G(几十个G用)
- G1 - (号称支持上百G)
- ZGC - 4T - 16T(JDK13)
1.8默认的垃圾回收: PS+ParallelOld
Root Searching(根搜索)
连着xx的都不是垃圾
xx:
JVM stack(栈里面还存活的)
native method stack(本地方法栈)
runtime constant pool(运行常量池)
static references in methodarea(静态引用)
Clazz
6.JVM调优第一步
JVM命令行参数参考
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
标准: - 开头,所有的HotSpot都支持
非标准: -X 开头,特定版本HotSpot支持特定命令
不稳定: -XX 开头,下个取消
常用:
-XX:+PrintFlagsFinal
设置值(最终生效值)
-XX:+PrintFlagsInitial
默认值
-XX:+PrintCommandLineFlags
查看命令行参数
java -XX+PrintFlagWithComments //只有debug版本能用
7总结
二 . 调优
1.什么是调优
1.吞吐量:用户代码时间/(用户代码执行时间+垃圾回收时间)
2.响应时间:STW越短,响应时间越好
所谓调优,首先确定,追求啥?吞吐量优先,还是响应时间优先?还是在满足一定的响应时间的情况下,要求达到
多大的吞吐量…
1.根据需求进行JVM规划和预调优
2.优化运行JVM运行环境(慢,卡顿)
3.解决VM运行过程中出现的各种问题(OOM)