JVM垃圾收集器

发布于:2022-08-06 ⋅ 阅读:(325) ⋅ 点赞:(0)

一、对象内存回收

1、引用计数器算法

有弊端

给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加1;当引用失效,计数器就减1;任何时候计数器为0 的对象就是不可能再被使用的。

2、可达性分析算法

将“GC Roots” 对象作为起点,从这些节点开始向下搜索引用的对象,找到的对象都标记为非垃圾对象,其余未标记的 对象都是垃圾对象

GC Roots根节点:线程栈的本地变量、静态变量、本地方法栈的变量等等。

二、垃圾收集器算法

 

1、分代收集理论

当前虚拟机都采用的分代收集理论。根据java堆的新生代和老年代的特点选择合适的垃圾收集算法。

比如新生代中每次收集都会有大量对象死去,所以选择复制算法。而老年代对象存活几率比较高,而且没有额外的空间对它进行分配担保,所以必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。

注意:“标记-清除”或“标记-整理”算法会比复制算法慢10倍以 上。

2、复制算法

为了解决效率问题,“复制”收集算法出现,可以将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块中,然后把使用的空间清理的。

 3、标记-清除算法

算法分为“标记”和“清除”阶段:标记存活的对象, 统一回收所有未被标记的对象(一般选择这种);也可以反过来

它是最基础的收集算法,比较简单,但是会带来 两个明显的问题:

  1.  效率问题 (如果需要标记的对象太多,效率不高) 

  2. 空间问题(标记清除后会产生大量不连续的碎片)

4、标记-整理算法

 根据老年代的特点特出的一种标记算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象回收,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。

三、垃圾收集器

 如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。

1、Serial收集器[ˈsɪriəl] (-XX:UseSerialGC -XX:UseSerialOldGC)

串行收集器是单线程收集器,在工作时只会使用一条垃圾收集器去做垃圾收集工作,同时必须暂停其他所有的工作线程,直到它收集结束。

新生代采用复制算法,老年代采用标记-整理算法。

2、Parallel Scavenge [ˈpærəlel] [ˈskævɪndʒ]收集器(-XX:UseParallelGC -XX:UseParallelOldGC)

Paralle收集器其实就是Serial收集器的多线程版本。关注的点是吞吐量(高效率的利用CPU)。CMS等垃圾收集器的关注点更多的是用户线程的停顿时间(提高用户体验)。所谓吞吐量就是CPU中用于运行用户代码的时间与CPU总消耗时间的比值。

但是也提供了很多的参数供用户找到最合适的停顿时间或最大吞吐量。

新生代采用复制算大,老年代采用标记-整理算法。

JDK8默认的新生代和老年代收集器

3、ParNew收集器(-XX:+UseParNewGC)

ParNew收集器其实和Parallel收集器很类似,区别主要在于它可以和CMS收集器配合使用

新生代采用复制算法,老年代采用标记-整理算法

它是许多运行在Server模式下的虚拟机的首要选择,除了Serial收集器外,只有它能与CMS收集器(真正意义上的并发收集器)配合工作

4、CMS收集器(-XX:+UseConcMarkSweepGC(old))

CMS收集器是一种以获取最短回收停顿时间为目标的收集器。它非常符合在注重用户体验的应用上使用。是HotSpot虚拟机第一个真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程同时工作。

使用标记-清除算法。

  • 初始标记:暂停所有的其他线程(STW),并记录下gc roots直接能引用的对象,速度很快。

  • 并发标记:并发标记阶段就是从GC Roots的直接关联对象开始遍历整个对象的过程,这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行。因为用户程序继续运行,可能会有导致已经标记过的对象状态发生改变。

  • 重新标记:重新标记是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录。这个阶段的停.顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。主要用到三色标记里的增量更新算法做重新标记。

  • 并发清理:开启用户线程,同时GC线程开始对未标记的区域做清扫。这个阶段如果有新增对象会被标记为黑色不做任何处理。

  • 并发重置:重置本次GC过程的标记数据

主要优点:并发收集、低停顿。

缺点:

  • 对CPU资源敏感(会和服务抢资源);

  • 无法处理浮动垃圾(在并发标记和并发清理阶段又产生垃圾,这种浮动垃圾只能等到下一次gc再清理了);

  • 它使用的回收算法-“标记-清除”算法会导致收集结束时会有大量空间碎片产生,当然通过参数XX:+UseCMSCompactAtFullCollection可以让jvm在执行完标记清除后再做整理

  • 执行过程中的不确定性,会存在上一次垃圾回收还没执行完,然后垃圾回收又被触发的情况,特别是在并 发标记和并发清理阶段会出现,一边回收,系统一边运行,也许没回收完就再次触发full gc,也就是"concurrent mode failure",此时会进入stop the world,用serial old垃圾收集器来回收

亿级流程电商系统如何优化JVM参数设置(ParNew + CMS)

5、G1收集器(-XX:+UseG1GC)

G1是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器。以极高的效率满足GC停顿时间要求的同时,还具备高吞吐量性能特征。

 

G1垃圾收集器对于对象什么时候会转移到老年代跟之前讲过的原则一样,唯一不同的是对大对象的处理,G1有专门分配 大对象的Region叫Humongous区[hjuːˈmʌŋɡəs],而不是让大对象直接进入老年代的Region中。 在G1中,大对象的判定规则就是一 个大对象超过了一个Region大小的50%,比如按照上面算的,每个Region是2M,只要一个大对象超过了1M,就会被放 入Humongous中,而且一个大对象如果太大,可能会横跨多个Region来存放。

Humongous区专门存放短期巨型对象,不用直接进老年代,可以节约老年代的空间,避免因为老年代空间不够的GC开 销。

Full GC的时候除了收集年轻代和老年代之外,也会将Humongous区一并回收。

G1收集器一次GC的运作过程:

  • 初始标记(initial mark,STW):暂停所有的其他线程,并记录下gc roots直接能引用的对象,速度很快 ;

  • 并发标记(Concurrent Marking):同CMS的并发标记 

  • 最终标记(Remark,STW):同CMS的重新标记 

  • 筛选回收(Cleanup,STW):筛选回收阶段首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间(可以用JVM参数 -XX:MaxGCPauseMillis指定)来制定回收计划

 

 

 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到