垃圾回收机制

本文详细解析了垃圾回收的基本原理,包括自动垃圾收集、可达性分析算法、引用类型及垃圾收集算法等内容。介绍了分代收集策略,以及串行、并行、并发等多种垃圾收集器的工作机制,帮助读者全面了解垃圾回收的实现细节。

目录

1、自动垃圾收集

2、可达性分析算法

3、引用类型

4、可达性级别

5、垃圾收集算法

6、分代收集

7、垃圾收集器


1、自动垃圾收集

垃圾收集器查看堆内存,自动识别删除未使用对象,回收未被引用对象使用的内存。
通过可达性分析,标记哪些内存需要被回收。

2、可达性分析算法

跟踪引用链条:GC Root根对象-->引用对象-->...,即对象及其应用对象的关系链,若一个对象和GC Roots之间不可达,也就是不存在应用,那么即可认为是可回收对象。

可以作为GC Root的对象:
虚拟机栈中正在引用的对象、本地方法栈中正在引用的对象、静态属性引用的对象、方法区常量引用的对象

3、引用类型

强引用:不会被回收
软引用:JVM在内存不足时,才会去试图回收软引用指向的对象。(缓存场景)
弱引用:随时可能被回收
虚引用:不能通过它访问对象。(也叫幻象引用)

4、可达性级别

强可达:一个对象可以有一个或多个线程在不通过各种引用的情况下都能访问到,意味着随时、随地都能引用,这个对象不会被回收。
软可达:只能通过软引用才能访问到对象的状态。
弱可达:只能通过弱引用访问时的状态。当弱引用被清除时,就符合销毁条件。
幻象可达:不存在其他引用,只有幻象引用指向这个对象。
不可达:意味着对象可以被清除了。

5、垃圾收集算法

标记-清除算法(Mark-Sweep):首先标识出所有要回收的对象,然后进行清除。效率有限,有内存碎片化问题,不适合特别大的堆;收集算法基本基于标记-清除的思路进行改进。
复制算法(Copying):划分两块同等大小的区域,收集时将活着的对象复制到另一块区域。拷贝过程中将对象顺序放置,就可以避免内存碎片化。复制+预留内存,有一定的浪费。
标记-整理算法(Mark-Compact):类似于标记-清除,但为避免内存碎片化,它会在清理过程中将对象进行移动,以确保移动后的对象占用连续的内存空间。

6、分代收集

主流JVM采用分代回收,根据对象的存活周期,将内存划分为几个区域,不同区域采用合适的垃圾收集算法。
堆内存:划分为新生代+老年代,内存占比1:2

  • 新生代:S0:S1:Eden,内存占比1:1:8,采用复制收集算法:

  新对象分配到Eden中,第一次垃圾收集,标记Eden中存活的对象,复制到S0,标记经历的回收次数,回收不在使用的对象
  第二次垃圾收集,标记Eden与S0中存活的对象,复制到S1,标记经历的回收次数,回收不在使用的对象
  ...
  存活的对象轮流循环被复制到S0,再到S1
  当经历回收次数>指定值时,认为对象长期持久存活,复制到老年代(指定次数:-XX:MaxTenuringThreshold=15),查询GC日志、动态年龄计算
  当存活对象复制到S区内存已满/不够用时,复制到老年代
  当新生代内存不够时,新生成对象直接到达老年代
  当大对象被创建时,直接存放至老年代(大对象阈值:-XX:+PretenureSizeThreshold,超过直接进入老年代)

  • 老年代:标记-整理算法。

7、垃圾收集器

1.串行收集器 Serial GC(-XX:+UseSerialGC) Serial Old(-XX:+UseSerialOldGC)
单个线程执行所有垃圾收集工作,适合单处理器机器。client模式下JVM的默认选项。
在新生代使用(Serial GC),采用复制算法;在老年代使用(Serial Old),采用标记-整理算法。
GC线程运行垃圾收集时会暂停用户线程,GC完成后用户线程恢复工作,会造成用户任务响应延时。

2.并行收集器 Parallel GC(-XX:+UseParallelGC) Parallel Old(GC -XX:+UseParallelOldGC)
新生代(Parallel GC)和老年代(Parallel Old)GC都是并行进行。server模式下JVM的默认选项。
可以设置GC时间或吞吐量等值,可以自动进行适应性调整Eden、Survivor大小和MaxTenuringThreshold的值。
也称为吞吐量优先的GC:吞吐量=用户代码运行时间/(用户代码运行时间+GC时间)
GC时依然会暂停用户线程。
JDK默认的收集器。

3.并发收集器 CMS GC(-XX:+UseConcMarkSweepGC)
专用于老年代,采用标记-清除算法,GC时不会停止用户线程,目标是尽量减少停顿时间。
初始标记(GC Root) -- 并发标记(多个GC线程与用户线程并发执行) -- 重新标记 -- 并发清除
初始标记和重新标记时会有短暂停顿,存在内存碎片化问题,长时间运行等情况下发生full GC,导致恶劣的停顿。(full GC:对堆内存进行全局GC,成本较大)
并发标记时会占用更多CPU资源,会和用户线程争抢资源。
响应时间优先。
Oracle在后续1.8中已放弃维护。

4.并行收集器 ParNew GC(-XX:+UseParNewGC)
专用于新生代,是Serial GC的多线程版本。
可以控制线程数量:-XX:ParallelGCThreads
最常见应用场景是配合老年代的CMS GC工作:-XX:+UseConcMarkSweepGC

5.并发收集器 G1(-XX:+UseG1GC)
JDK1.7开始使用,CMS GC的替代者,JDK1.9后未默认选型。
针对大堆内存设计的收集器,兼顾吞吐量和停顿时间(响应时间)。
与其它收集器分代方式不同,G1将堆分成固定大小的区域,区域可以是新生代(Eden+Surivor),可以是老年代,也可以是新生代老年代共同存在,每个区域(Region)采用复制算法,但整体上可看作是标记-整理算法,对区域进行内存整理,将有内容的区域挪到一块,有效避免内存碎片化,找不到大内存时执行FullGC。
虽然是并发执行,但仍会有短暂暂停,标记时、新生代收集时、混合收集时(多种垃圾收集+空间整理)、垃圾清除时。
超过50%的Java堆被实时数据占用。
建议大堆(大小约为6G或更大)

6.并发收集器 ZGC
染色指针、内存分页、转发表、读屏障
复制算法 + 标记 - 清除算法

垃圾收集器组合方式:
CMS + ParNew
Parallel GC + Parallel Old(默认)
Serial GC + Serial Old
G1(新生代老年代兼容)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值