美文网首页程序员
jvm垃圾回收器

jvm垃圾回收器

作者: 三不猴子 | 来源:发表于2020-06-23 21:53 被阅读0次

垃圾回收器

什么是垃圾对象?

没有任何引用的对象。

如何发现垃圾对象?

  1. reference count 引用计数
    • 每引用一次给计数器+1,减少一次引用进行-1。
    • 无法解决的问题,循环引用。A引用B,B引用C,C引用A,但是ABC三个整体没有被其他的引用。 ABC整体应该是一个垃圾,引用计数无法发现。
  2. root search 根可达算法
    1. 从线程对象(main方法)出发搜索对象是否可达。
    2. 从静态变量出发。
    3. 常量池
    4. JNI指针,c++实现的本地方法


      image.png

    GC Algorithms 垃圾清除算法

    1. Mark-Sweep (标记清除)将不可用的对象标记,然后清除。
      1. 优点:
        • 算法实现简单
        • 存活对象较多时效率较高
      2. 缺点
        • 扫描两遍(第一次找出不可用对象并标记,第二遍遍历清除)效率较低
        • 容易产生碎片
    2. copy(拷贝)将内存一份为二,将可用的对象拷贝到一块区域。
      1. 优点:
        • 对象存活较少的情况下只扫描一遍,效率较高
        • 没有碎片
      2. 缺点:
        • 浪费空间
        • 移动复制对象,需要调整对象引用
    3. Mark-Compact (标记压缩)将可用对象移动至内存的某个区域,剩下的就是大块的不可用的区域,再删除不可用的。
      1. 优点
        • 不会产生内存碎片,方便对象分配
        • 不会内存减半
      2. 缺点
        • 扫描两次效率较低
        • 需要移动对象,效率较低

堆内存逻辑分区(不适合不分代的垃圾收集器,除Epsilon、ZGC、shenandoah之外都是逻辑分代模型,G1是逻辑分代不是物理分代,除此之外不仅逻辑分代而且还是 物理分代)

  1. 新生代:大量死去少量存活,采用的复制算法。eden、survivor1、survivor2默认比例是8:1
    1. eden:初生代
    2. survivor:有两块survivor区域
  2. 老年代:有大量存活,少量死亡,采用ms(Mark swap标记清除)或mc(Mark compact 标记压缩)算法。
    1. tenured:老年代或者叫永久代。

一个对象的消亡过程

  1. 尝试在栈上分配
    • 能在栈分配必须满足:
      • 线程私有小对象
      • 无逃逸
      • 支持标量替换(对象可以一个或多个基本类型替换)

对象的生命周期会随着方法的调用开始而开始,方法的调用结束而结束,对于这种对象,是不是该考虑将对象不在分配在堆空间中呢?因为一旦分配在堆空间中,当方法调用结束,没有了引用指向该对象,该对象就需要被gc回收,而如果存在大量的这种情况,对gc来说无疑是一种负担

  1. 进入Eden
    1. Eden 区默认1%的区域有个叫TLAB(Thread Local Allocation Buffer)多线程不用竞争就可以申请空间提高效率。
  2. Eden存活下来,进入survivor1
  3. survivor1存活下来进入survivor2
  4. survivor2存活下来进入survivor1如此往复,指导达到配置好的代数,后进入老年代。
    MiniorGC/YGC: 年轻代空间耗尽触发。
    MajorGC/FullGC:老年代空间不足,触发年轻代和老年代同时回收

对象何时进入老年代

  1. 超过-XX:MaxTenuringThreshold 指定数值
    1. PS 15
    2. CMS 5
    3. G1 15
  2. 动态年龄
    • Survivor(Eden + s1 +s2)区的对象年龄从小到大进行累加,当累加到 X 年龄时的总和大于50%(可以使用-XX:TargetSurvivorRatio=? 来设置保留多少空闲空间,默认值是50),那么比X大的都会晋升到老年代
  3. 分配担保
    在发生minor gc之前,虚拟机会检测 : 老年代最大可用的连续空间 > 新生代all对象总空间?
    1、满足,minor gc是安全的,可以进行minor gc。
    2、不满足,虚拟机查看HandlePromotionFailure参数:
    • 为true,允许担保失败,会继续检测老年代最大可用的连续空间>历次晋升到老年代对象的平均大小。若大于,将尝试进行一次minor gc,若失败,则重新进行一次full gc。
    • 为false,则不允许冒险,要进行full gc(对老年代进行gc)。

常见的垃圾回收器

Serial收集器

Serial收集器是最基础、历史最悠久的收集器,曾经(在JDK 1.3.1之前)是HotSpot虚拟机新生代 收集器的唯一选择。是个单线程的垃圾回收器,这里的单线程强调的不是这个回收器是由一个核心的一个线程完成,强调的是“stop the world”,该垃圾回收线程工作时必须停掉其他工作线程。

适用场景:对于单核处理器或处理器核心数较少的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率。

类型:新生代回收器

ParNew收集器

是Serial收集器的多线程并行版本,ParNew收集器实质上是Serial收集器的多线程并行版本,除了同时使用多条线程进行垃圾收集之外 , 其余的行为包括Serial收集器可用的所有控制参数(例如:-XX:SurvivorRatio、-XX:PretenureSizeThreshold、-XX:HandlePromotionFailure等)、收集算法、Stop The World、对象分配规则、回收策略等都与Serial收集器完全一致但它却是不少运行在服务端模式下的HotSpot虚拟机,经管如此,尤其在jdk7之前还是有大量的服务端适用的是ParNew,重要原因就是只有它可以配合CMS使用。

类型:新生代回收器

适用场景:ParNew+CMS 第一款真正意义上支持并发的垃圾收集器,它首次 实现了让垃圾收集线程与用户线程(基本上)同时工作。

并行(Parallel):并行描述的是多条垃圾收集器线程之间的关系,说明同一时间有多条这样的线 程在协同工作,通常默认此时用户线程是处于等待状态。

并发(Concurrent):并发描述的是垃圾收集器线程与用户线程之间的关系,说明同一时间垃圾 收集器线程与用户线程都在运行。由于用户线程并未被冻结,所以程序仍然能响应服务请求,但由于 垃圾收集器线程占用了一部分系统资源,此时应用程序的处理的吞吐量将受到一定影响。

Parallel Scavenge收集器

Parallel Scavenge收集器的特点是它的关注点与其他收集器不同,CM S等收集器的关注点是尽可能 地缩短垃圾收集时用户线程的停顿时间,而Parallel Scavenge收集器的目标则是达到一个可控制的吞吐 量(Throughput)。

  1. -XX:MaxGCPauseMillis 控制最大垃圾收集停顿时间
  2. -XX:GCTimeRatio 直接设置吞吐量

适用场景:优先考虑吞吐量的应用,而不是STW时间。

类型:新生代垃圾回收器

Serial Old收集器

Serial Old是一个使用标记整理算法的单线程收集器。这个垃圾回收器主要也是提供给客户端模式下使用的,Parallel Scavenge收集器架构中本身有PS MarkSweep收集器来进行老年代收集,并非直接调用Serial Old收集器,PS MarkSweep收集器与Serial Old的实现几乎是一样的,所以在官方的许多资料中都是直接以Serial Old代替PS MarkSweep进行讲解。

适用场景:单核处理器或处理器核心数较少的环境,内存也不是特别大的场景。

类型:老年代回收器

Parallel Old收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实 现。这个收集器是直到JDK 6时才开始提供的,在此之前使用Parallel Scavenge只能选择Serial Old(PS MarkSweep)其他表现性能较好的如CMS无法使用,由于Serial Old表现并不突出,所以使用Parallel Scavenge并不能获得吞吐量上的提升。

适用场景:搭配Parallel Scavenge使用

类型:老年代回收器

CMS收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。更短的停顿时间可以获的更短的响应时间。收集过程包括以下几个部分

  1. 初始标记(CMS initial mark)
  2. 并发标记(CM S concurrent mark)
  3. 重新标记(CM S remark)
  4. 并发清除(CM S concurrent sweep)

常见垃圾回收器组合参数设定:(1.8)

  • -XX:+UseSerialGC = Serial New (DefNew) + Serial Old
    • 小型程序。默认情况下不会是这种选项,HotSpot会根据计算及配置和JDK版本自动选择收集器
  • -XX:+UseParNewGC = ParNew + SerialOld
  • -XX:+UseConc(urrent)MarkSweepGC = ParNew + CMS + Serial Old
  • -XX:+UseParallelGC = Parallel Scavenge + Parallel Old (1.8默认) 【PS + SerialOld】
  • -XX:+UseParallelOldGC = Parallel Scavenge + Parallel Old
  • -XX:+UseG1GC = G1
  • Linux中没找到默认GC的查看方法,而windows中会打印UseParallelGC
    • java +XX:+PrintCommandLineFlags -version
    • 通过GC的日志来分辨
  • Linux下1.8版本默认的垃圾回收器到底是什么?
    • 1.8.0_181 默认(看不出来)Copy MarkCompact
    • 1.8.0_222 默认 PS + PO

相关文章

网友评论

    本文标题:jvm垃圾回收器

    本文链接:https://www.haomeiwen.com/subject/noykfktx.html