专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

jvm垃圾回收

垃圾回收器

什么是垃圾对象?

没有任何引用的对象。

如何发现垃圾对象?

1、 reference count 引用计数

 *  每引用一次给计数器+1,减少一次引用进行-1。
 *  无法解决的问题,循环引用。A引用B,B引用C,C引用A,但是ABC三个整体没有被其他的引用。 ABC整体应该是一个垃圾,引用计数无法发现。

2、 root search 根可达算法

1.  从线程对象(main方法)出发搜索对象是否可达。
2.  从静态变量出发。
3.  常量池
4.  JNI指针,c++实现的本地方法 ![76\_1.png][76_1.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

文章永久链接:https://tech.souyunku.com/29112

未经允许不得转载:搜云库技术团队 » jvm垃圾回收

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们