关于JVM你需要知道的——垃圾回收GC

本文详细介绍了JVM垃圾回收的基本原理和技术实现,包括如何判断对象是否存活、不同的垃圾回收算法及其应用场景,以及常见垃圾收集器的特点和配置参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JVM中垃圾回收的内存区域主要指堆。虽然HotSpot对方法区也会进行垃圾回收,但是不在JVM的规范里。通过垃圾回收调优,尽可能减少垃圾回收的次数和时间,是我们的目标。

垃圾收集器需要完成两部分工作:判断对象是否存活和回收内存。

判断对象是否存活

JVM从所有GCRoot对象出发,遍历他们引用的对象。没被遍历到的对象表示已经死亡。
GCRoot对象包括:

  • 虚拟机栈中引用到的对象
  • 本地方法栈中引用到的对象
  • 方法区中静态变量引用到的对象
  • 方法去中常量引用到的对象
回收方法
  • 复制-清除
    1092610-20170209013605494-908578320.png
    将内存分为大小相等的两块。将其中一块A作为工作区,当A可用内存不够时,将存活对象复制到另一块B,并将其改为工作区,清除A中的所有对象回收内存。当B可用内存不够时,将存活对象复制到A,并将A改为工作区,周而复始。缺点是可用内存最多只有全部内存的一半。
  • 标记-清除(Mark-Sweep)
    1092610-20170209005504963-251710476.png
    缺点是造成内存碎片过多,可能无法存放大对象
  • 标记-整理(Mark-Compact)
    1092610-20170209005334041-567218533.png
    在标记-清除的基础上将存活对象移动到一块。缺点是耗时长
  • 分代
    这是JVM采用的回收方法,综合了前面的三种方法。
    1092610-20170209013124588-1661544220.png
    在新生代中采用复制-清除,在年老代中采用标记-清除或标记-整理,取决于使用的垃圾收集器:
  1. 刚new的对象保存在eden
  2. eden空间用完以后,进行Minor GC,将eden中的对象复制到to空间,并清空eden空间,再把to和from空间互换
  3. 继续new对象保存在eden,eden空间用完后,进行Minor GC,将from和eden中的对象复制到to空间,并清空eden和from空间,再把to和from空间互换
  4. 如果对象经历的Minor GC次数超过了一定的阈值threshold,就移到年老代中
  5. 年老代中空间用完就会触发Major GC,对年老代进行垃圾回收
垃圾收集器

JVM常见的垃圾收集器有以下几种:

名称作用空间方法运行方式启用参数特点
Serial新生代复制-清除单线程,串行-XX:+UseSerialGC
ParNew新生代复制-清除多线程,并行-XX:+UseParNewGC停顿时间短
Parallel Scavenge新生代复制-清除多线程,并行-XX:+UseParallelGC吞吐量高
Serial Old年老代标记-整理单线程,串行-XX:+UseSerialGCCMS备用
Parallel Old年老代标记-整理多线程,并行-XX:+UseParallelOldGC吞吐量高
CMS年老代标记-清除多线程,并发-XX:+UseConcMarkSweepGC停顿时间短

除CMS外的其他收集器工作时都会使应用停止运行。CMS实现了垃圾收集器线程与用户线程同时工作,实现了最短停顿时间。因为CMS采用了标记-清除方法,所以CMS会造成内存碎片。在应用产生死亡对象的速度高于回收速度或者内存碎片过多无法满足大对象要求时,CMS回收会失败,这个时候会运行一次Serial Old收集器。

  • 在与用户交互比较多,追求响应速度的场景下,选择ParNew和CMS
  • 在进行后台数据处理,追求吞吐量的场景下,选择Parallel Scavenge和Parallel Old
垃圾收集器调优
  1. -XX:ParallelGCThreads=10 并行收集器的线程数
  2. -XX:MaxTenuringThreshold=31 经过31次Minor GC的对象放入到年老代中,这里只是指定最大值,实际阈值通过XX:TargetSurvivorRatio计算得到
  3. -XX:PretenureSizeThreshold=1024 单位字节,超过一定大小的对象直接放入年老代,不放入to
  4. -XX:TargetSurvivorRatio=50 把from中经过Minor GC次数最多的对象移到年老代中,直到最后to已用空间的大小小于to空间的50%
  5. -XX:+UseCMSCompactAtFullCollection CMS收集器运行完后是否进行内存整理,减少内存碎片,默认打开
  6. -XX:CMSFullGCsBeforeCompaction=5 CMS收集器每运行6次就执行一次内存整理,默认0,也就是每次都执行
  7. -XX:CMSInitiatingOccupancyFraction=60 CMS收集器在年老代使用空间超过60%时进行垃圾回收
  8. -XX:+CMSClassUnloadingEnabled CMS收集器在方法区进行垃圾回收
  9. -XX:+DisableExplicitGC 禁止显式GC,System.gc()

注意 相关垃圾回收信息可以通过jstat获得

补充

从jdk1.7开始,JVM支持G1垃圾回收器。G1将整个内存空间分成多个region,机动分配给新生代和年老代,垃圾回收线程优先回收垃圾最多的region。回收效率低于CMS,但是不会和CMS一样,因为内存不够就不停的fullGC,造成垃圾回收雪崩的现象。G1最大的特点是能够设定应用的停滞时间,默认200ms,比较适合于分布式流式数据处理系统。使用方式-XX:+useG1GC

转载于:https://www.cnblogs.com/hanzai/p/6380373.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值