JVM_垃圾回收基础知识
文章目录
一个对象创建的内存分配过程
- 先尝试在栈上分配:经过逃逸分析和标量替换。
- 栈上创建对象的好处:栈内对象出栈之后,生命周期结束,不需要GC介入。
- TLAB:thread local allocation buffer线程本地分配缓冲区,,调度线程的分配竞争。
GC的基础知识
1.什么是垃圾
C语言申请内存:malloc free
C++: new delete
Java: new ?
自动内存回收,编程上简单,系统不容易出错,手动释放内存,容易出两种类型的问题:
- 忘记回收
- 多次回收
- 垃圾指没有任何引用指向的一个对象或者多个对象(循环引用,垃圾堆)。
java的调优机制就集中在垃圾回收器的选择和参数设置上。
2.如何定位垃圾
- 引用计数(有缺陷:三个对象循环引用,但是没有栈引用,造成无法回收,内存泄漏。)
- 根可达算法(root searching),根对象有引用的,不回收,其他都是垃圾。
根对象包括哪些?
3.常见的垃圾回收算法
-
标记清除(mark-sweep) - 位置不连续 产生碎片(两遍扫描)
-
拷贝算法(copying) - 没有碎片,浪费空间
-
标记压缩(mark-compact) - 没有碎片,效率偏低(两遍扫描,内存移动需要线程同步,影响效率)
4.JVM内存分代模型(用于分代垃圾回收算法)
-
部分垃圾回收器使用的模型
-
新生代 + 老年代 + 永久代(1.7)/ 元数据区(1.8) Metaspace
- 永久代 元数据 - Class
- 永久代必须指定大小限制 ,元数据可以设置,也可以不设置,无上限(受限于物理内存,由操作系统管理)
- 字符串常量 1.7 - 永久代,1.8 - 堆
- MethodArea逻辑概念 - 永久代、元数据
-
新生代 = Eden + 2个suvivor区
- YGC回收之后,大多数的对象会被回收,活着的进入s0
- 再次YGC,活着的对象eden + s0 -> s1
- 再次YGC,eden + s1 -> s0
- 年龄足够 -> 老年代 (15 CMS 6)
- s区装不下 -> 老年代
-
老年代
- 顽固分子
- 老年代满了FGC Full GC(包括新生代和老年代全部gc一次)
-
GC Tuning调优 (Generation 针对于分代模型)
- 尽量减少FGC(效率很底,可能会系统停顿)
- MinorGC = YGC
- MajorGC = FGC
5.常见的垃圾回收器(垃圾收集器就是算法落地实现)
jvm的内存模型归gc回收器模型管
-
Serial (stw:stop the world)年轻代 串行回收(小孩子扔线团和妈妈清理的场景。)
-
PS 年轻代 并行回收(小孩子扔线团和长辈一起清理的场景。)
-
ParNew 年轻代 配合CMS的并行回收(约等于PS,可以配合CMS用)
-
SerialOld
-
ParallelOld
-
ConcurrentMarkSweep (CMS)老年代 并发的, 垃圾回收和应用程序同时运行,降低STW的时间(降低至200ms以内)
-
G1(10ms)(jdk1.9以上默认)
-
ZGC (1ms) PK C++
-
Shenandoah
-
Eplison(jdk11新加,不回收垃圾,jvm调试用)
jvm1.8默认的垃圾回收:PS + ParallelOld
6.垃圾收集器的发展
-
垃圾回收器的演进与内存的大小发展有关系,内存越大与回收线程越多并不呈线性正相关,因为CPU性能(瓶颈)受限于线程切换(contextSwitch),影响gc清理。
-
因此诞生了CMS(缺点:内存碎片化,浮动垃圾,此时若有大对象进来,调用serial old来清理腾地方,卡顿时间很久),jdk第一个并发执行的垃圾回收器,CMS的4个阶段:
- 初始标记:标记根对象(STW)
- 并发标记(mark sweep):并行;存在标记的重复利用(错标,严重),不用的没标记的问题(漏标,浮动垃圾)
- 重新标记(STW),修改错标,又重新扫描一遍。
- 并发清理。
- 怎么标记?怎么修改?并发标记算法(三色标记算法)
- 错标
- cms的解决方案:A产生新的引用,重新变灰
-
G1的产生
-
告别物理分代,进行逻辑分代,分而治之。
-
G1处理java文件的运行效率比其他的垃圾回收器的效率慢3%-4%(问题不大),因为存在**屏障(新建对象的时候),用于垃圾回收的标记。
-
7.JVM调优第一步,了解生产环境下的垃圾回收器组合
-
JVM的命令行参数参考:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
-
JVM参数分类
标准: - 开头,所有的HotSpot都支持
非标准:-X 开头,特定版本HotSpot支持特定命令
不稳定:-XX 开头,下个版本可能取消
-XX:+PrintCommandLineFlags
-XX:+PrintFlagsFinal 最终参数值
-XX:+PrintFlagsInitial 默认参数值