gc-初步介绍

jvm内存区域

如何识别垃圾

回收算法

回收器

参考


jvm内存区域

一起看下内存区域:

  •  虚拟机栈

线程私有,方法被执行时创建栈帧,主要保存方法中的局部变量表、操作数栈、动态链接、方法返回地址。方法调用时入栈,方法返回是出栈清除,不需要GC

  • 本地方法栈

与虚拟机栈类似, 不过本地方法栈服务于本地方法调用

  • 程序计数器

线程私有,线程获得处理器时间片执行时,从程序计数器取出对应的字节码行号,进行程序运行,不需要GC

  • 本地内存

注意java8和java8之前的区别,在j8之前方法区存在堆中,用于储存类信息、常量、静态变量、即时编译器生成的代码等信息,受XX:PermSize控制,存在出现OOM的可能; 在j8之后,该区域迁移到堆外内存中,提升了性能(该区域不再进行gc,不会有stw),因此也不需要GC

注意:j8之后的方法区内存如何回收?在直接内存申请时会创建堆内对象,堆内对象被回收时会将堆外内存对应的地址指针加入队列,清理程序会对队列进行回收

堆是对象创建时分配的区域,需要GC

如何识别垃圾

  • 引用计数法

原理很简单,记录对象被引用的次数,次数为0时可以回收。

看起来算法很简单,但是实现起来不是那么回事,对于循环引用的对象难以回收,所以jvm并没有采用此算法。

注:不过在redis采用了此类的方法,以后分析redis的时候再一起看这个问题 

  • 可达性算法

原理:以GC Roots对象为起点,找出它们引用的对象,再以被引用的对象为起点,找出它们引用的对象,依次类推,进行标记,对于其它不在此引用链中的对象,可以进行回收

对于图上的a 和 b就属于可回收对象,但是它们还有一次逃出被回收的机会,jvm在回收时执行对象的finalize方法,在此方法中,如果对象重新加入GC Roots链,则对象不会被回收,但是finalize方法只会执行一次

什么是GC Roots?

  1. 虚拟机栈中引用的对象
  2. 方法区中常量引用的对象
  3. 方法区中静态变量引用的对象
  4. 本地方法栈中jni引用的对象

 回收算法

  • 标记清除

可达性算法标记可回收对象--> 进行清除回收

  • 复制算法

将内存分为2部分,在一部分中进行分配,回收时,将存活的对象复制到另一部分

  • 标记整理

标记清除的升级,标记清除无疑会带来内存碎片,标记整理在回收时将存活的对象向一端移动,回收另一端内存

  • 分代回收

将内存分为 新生代、老生代(j8以前有永久代),比例1:2,新生代分为eden/from survivor/to survivor,比例8:1:1

如何回收

a. 新生代发生的gc叫做YGC,老生代发生的GC叫做FGC

b. 创建对象会分配在eden区域,eden区域内存不足时发生ygc,该区域由于大部分对象都是可回收的,因此采用复制算法进行回收

如何晋升老生代

a. 在ygc多次回收后依然存活的对象,晋升老生代

b. 大对象分配直接进入老生代

c. 对于survivor区域相同年龄的对象占用内存超过survivor一半以上时,所有年龄大于此年龄的对象晋升老生代

空间分配担保

在做ygc之前,vm检查是否允许HandlePromotionFailure晋升担保,如果允许,vm检查老生代的连续可用空间是否大于历次ygc晋升的所用空间,如果大于则进行ygc,否则进行fgc

STW

fgc会清理新生代和老生代,并且带来stw。stw是由于vm暂停了除垃圾回收期线程的所有线程

其中fgc带来的stw更长

fgc带来的stw会影响性能,因此需要选取合适的时间执行,这就是SafePoint,有以下几类:

a. 循环的末尾

b. 方法返回前

c. 调用方法之后

d. 抛出异常的位置

回收器

不同的发展阶段,针对不同的分代,产生了一系列回收器

  • Serial

单线程垃圾回收器,常用于client模式下

  •  ParNew

Serial的多线程版本,常用于server模式下,除了Serial外,只有ParNew收集器可以与CMS配合使用

  • Parallel Scavenge

目标是可控制吞吐量,因此ParNew常用于用户交互性服务,而此收集器常用于吞吐量优先的服务

  • Serial Old

Serial的老生代版本,常用于client模式下。如果用于server模式下,则主要作为cms失败的后备收集器

  • Parallel Scavenge Old

与Parallel Scavenge配合使用

  • CMS

优先减少stw时间,减少系统停顿,其回收有4个阶段

  1. 初始标记:标记GC Roots直接关联到的对象,有stw
  2. 并发标记:标记GC Roots tracing过程
  3. 重新标记:标记用户线程执行产生的可回收对象,有stw
  4. 并发回收:与用户线程并行

缺点

  1. cms回收线程会影响系统吞吐量
  2. 回收会产生内存碎片,需要设置-XX:CMSFullGCsBeforeCompation来设置回收时进行内存整理
  3. 回收的过程中,系统内存不足会导致current mode failure,需要使用serial old进行内存回收,带来更长的stw
  • G1

 并行垃圾收集器,与cms相比起优点在于

  1. region内采用标记整理算法、region间采用复制算法,不会产生内存碎片
  2. 可控制的stw时间

stw为啥可控呢?

  1. g1将内存分为n个大小相同的region
  2. 跟踪所有region的内存使用情况以及回收价值
  3. 根据stw的设置,筛选region进行回收

参考

https://mp.weixin.qq.com/s/JKSSGyL7c-QgbQ3F_VEoyQ

发布了22 篇原创文章 · 获赞 1 · 访问量 524

猜你喜欢

转载自blog.csdn.net/weixin_37512224/article/details/104326183