热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入浅析JVM垃圾回收机制与收集器概述

本文基于《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》的阅读心得进行整理,详细探讨了JVM的垃圾回收机制及其各类收集器的特点与应用场景。通过分析不同垃圾收集器的工作原理和性能表现,帮助读者深入了解JVM内存管理的核心技术,为优化Java应用程序提供实用指导。

作品标明出处:本文是对《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》阅读后的整理,有兴趣的同学可购买正版进行学习!


1.查看JVM默认垃圾收集器

java -XX:+PrintCommandLineFlags -version

上图中的 -XX:+UseParallelGC就是我们默认使用的收集器,新生代使用的是Parallel Scanvenge收集器,老年代使用的是Serial Old


2.JVM垃圾收集器常用参数

 


3.垃圾收集器

 如果两个收集器之间存在连线,就说明它们可以搭配使用 ,图中收集器所处的区域,则表示它是属于新生代收集器抑或是老年代收集器


  •  Serial收集器

新生代收集器,低延迟

单线程收集器:不仅仅是说明它只会使用一个处理器或一条收集线程去完成垃圾收集工作,更重要的是强调在它进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束,Stop The World!


  •  ParNew收集器

新生代收集器

是Serial收集器的多线程并行版本。

只有它能和CMS收集器搭配使用。

ParNew收集器是激活CMS后(使用-XX:+UseConcMarkSweepGC选项)的默认新生代收集器,也可以使用-XX:+/-UseParNewGC选项来强制指定或者禁用它。


  •  Parallel Scanvenge收集器

新生代收集器,标记--复制算法

和ParNew收集器非常相似,目标是达到一个可控制的吞吐量

 参数 -XX:+UseAdaptiveSizePolicy,垃圾收集的自适应调节策略,不需要人工指定新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象大小(-XX:PretenureSizeThreshold)等细节参数了,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量


  • Serial Old收集器

老年代单线程收集器,标记--整理算法

两种用途:

        1、在JDK 5以及之前的版本中与Parallel Scavenge收集器搭配使用 

        2、作为CMS收集器发生失败时的后备预案,在并发收集发生Concurrent Mode Failure时使用

.


  •  Parallel Old收集器

老年代多线程收集器,标记--整理算法

Parallel Scavenge + Parallel Old收集器搭配使用,吞吐量优先


  •  CMS收集器(Concurrent Mark Sweep)

老年代多线程收集器,标记--清除算法(收集结束可能会导致大量空间碎片,触发Full GC)

并发收集、低延迟,“并发低停顿收集器”(Concurrent Low Pause Collector)

整个过程分为四个步骤:

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

 JDK5默认启动阈值为老年代使用了 68%,

JDK6时默认阈值提升至92%,此时可能导致CMS运行期间预留的内存无法满足程序分配新对象的需要,就会出现一次“并发失败”(Concurrent Mode Failure),这时候虚拟机将不得不启动后备预案:冻结用户线程的执行,临时启用Serial Old收集器来重新进行老年代的垃圾收集


  • G1(Garbage First)收集器

面向整个堆空间多线程收集器,标记--整理算法,每个Region又是基于标记--复制算法

低延迟、

JDK9以后默认垃圾收集器

面向局部收集、基于Region内存布局

面向堆内存任何部分来组成回收集,衡量标准为哪块内存中存放的垃圾最多,会后收益最大,这就是G1收集器的Mixed GC模式

G1把连续的Java堆划分为多个大小相等的独立区域Region,每个Region都可以根据需要,扮演新生代的Eden空间、Survivor空间,或者老年代空间;Region中还有一类特殊的Humongous区域,专门用来存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象

每个Region大小可以通过参数-XX:G1HeapRegionSize设定,取值范围为1MB~32MB,且应为2的N次幂

而对于那些超过了整个Region容量的超级大对象,将会被存放在N个连续的Humongous Region之中,G1的大多数行为都把Humongous Region作为老年代的一部分来进行看待

 Region里面存在的跨Region引用对象如何解决?

 答:使用记忆集避免全堆作为GC Roots扫描,每个Region都维护有自己的记忆集,这些记忆集会记录下别的Region指向自己的指针,并标记这些指针分别在哪些卡页的范围之内。

由于Region数量比传统收集器的分代数量明显要多得多,因此G1收集器要比其他的传统垃圾收集器有着更高的内存占用负担。根据经验,G1至少要耗费大约相当于Java堆容量10%至20%的额外内存来维持收集器工作

G1收集器的四个步骤:

        1、初始标记(Initial Marking)

        2、并发标记(Concurrent Marking)

        3、最终标记(Final Marking)

        4、筛选回收(Live Data Counting and Evacuation)


  •  Shenandoah收集器

低延迟、并发收集,标记--整理算法

也是基于Region的堆内存布局,同样有着用于存放大对象的Humongous Region,默认的回收策略也同样是优先处理回收价值最大的Region

Shenandoah(目前)是默认不使用分代收集,不会有专门的新生代Region或者老年代Region的存在,没有实现分代

Shenandoah摒弃了在G1中耗费大量内存和计算资源去维护的记忆集,改用名为“连接矩阵”(ConnectionMatrix)的全局数据结构来记录跨Region的引用关系,降低了处理跨代指针时的记忆集维护消耗,也降低了伪共享问题的发生概率

Shenandoah收集器的工作过程大致可以划分为以下九个阶段:

        1、初始标记(Initial Marking)

        2、并发标记(Concurrent Marking)

        3、最终标记(Final Marking)

        4、并发清理(Concurrent Cleanup)

        5、并发回收(Concurrent Evacuation)

        6、初始引用更新(Initial Update Reference)

        7、并发引用更新(Concurrent Update Reference)

        8、最终引用更新(Final Update Reference)

        9、并发清理(Concurrent Cleanup)


  • ZGC

低延迟垃圾收集器,基于Region内存布局,并发标记-整理算法

ZGC的Region具有动态性——动态创建和销毁

在x64硬件平台下,ZGC的Region可以具有如图3-19所示的大、中、小三类容量:
        1、小型Region(Small Region):容量固定为2MB,用于放置小于256KB的小对象。
        2、中型Region(Medium Region):容量固定为32MB,用于放置大于等于256KB但小于4MB的对象。
        3、大型Region(Large Region):容量不固定,可以动态变化,但必须为2MB的整数倍,用于放置4MB或以上的大对象。每个大型Region中只会存放一个大对象

 ZGC收集器的运作过程:

        1、并发标记(Concurrent Mark)

        2、并发预备重分配(Concurrent Prepare for Relocate)

        3、并发重分配(Concurrent Relocate)

        4、并发重映射(Concurrent Remap)



推荐阅读
  • JUC并发编程——线程的基本方法使用
    目录一、线程名称设置和获取二、线程的sleep()三、线程的interrupt四、join()五、yield()六、wait(),notify(),notifyAll( ... [详细]
  • 在Java开发中,保护代码安全是一个重要的课题。由于Java字节码容易被反编译,因此使用代码混淆工具如ProGuard变得尤为重要。本文将详细介绍如何使用ProGuard进行代码混淆,以及其基本原理和常见问题。 ... [详细]
  • 本文探讨了Java中线程的多种终止方式及其状态转换,提供了关于如何安全有效地终止线程的指导。 ... [详细]
  • 深入解析JVM内存模型与分配机制
    本文详细探讨了JVM内存结构的主要组成部分,包括Java虚拟机栈、Java堆、方法区等,并深入分析了HotSpot虚拟机的分代收集策略及其对不同内存区域的管理方式。 ... [详细]
  • 关于进程的复习:#管道#数据的共享Managerdictlist#进程池#cpu个数1#retmap(func,iterable)#异步自带close和join#所有 ... [详细]
  • 在运行于MS SQL Server 2005的.NET 2.0 Web应用中,我偶尔会遇到令人头疼的SQL死锁问题。过去,我们主要通过调整查询来解决这些问题,但这既耗时又不可靠。我希望能找到一种确定性的查询模式,确保从设计上彻底避免SQL死锁。 ... [详细]
  • 深入理解Java多线程与并发机制
    本文探讨了Java多线程和并发机制的核心概念,包括多线程类的分类、执行器框架、并发容器及控制工具。通过详细解析这些组件,帮助开发者更好地理解和应用多线程技术。 ... [详细]
  • 本文介绍了SIP(Session Initiation Protocol,会话发起协议)的基本概念、功能、消息格式及其实现机制。SIP是一种在IP网络上用于建立、管理和终止多媒体通信会话的应用层协议。 ... [详细]
  • Beetl是一款先进的Java模板引擎,以其丰富的功能、直观的语法、卓越的性能和易于维护的特点著称。它不仅适用于高响应需求的大型网站,也适合功能复杂的CMS管理系统,提供了一种全新的模板开发体验。 ... [详细]
  • 一、Advice执行顺序二、Advice在同一个Aspect中三、Advice在不同的Aspect中一、Advice执行顺序如果多个Advice和同一个JointPoint连接& ... [详细]
  • 本文详细介绍了如何正确设置Shadowsocks公共代理,包括调整超时设置、检查系统限制、防止滥用及遵守DMCA法规等关键步骤。 ... [详细]
  • 深入理解Java SE 8新特性:Lambda表达式与函数式编程
    本文作为‘Java SE 8新特性概览’系列的一部分,将详细探讨Lambda表达式。通过多种示例,我们将展示Lambda表达式的不同应用场景,并解释编译器如何处理这些表达式。 ... [详细]
  • Bootstrap Paginator 分页插件详解与应用
    本文深入探讨了Bootstrap Paginator这款流行的JavaScript分页插件,提供了详细的使用指南和示例代码,旨在帮助开发者更好地理解和利用该工具进行高效的数据展示。 ... [详细]
  • Logging all MySQL queries into the Slow Log
    MySQLoptionallylogsslowqueriesintotheSlowQueryLog–orjustSlowLog,asfriendscallit.However,Thereareseveralreasonstologallqueries.Thislistisnotexhaustive:Belowyoucanfindthevariablestochange,astheyshouldbewritteninth ... [详细]
  • 本文详细介绍了 Java 中 org.w3c.dom.Node 类的 isEqualNode() 方法的功能、参数及返回值,并通过多个实际代码示例来展示其具体应用。此方法用于检测两个节点是否相等,而不仅仅是判断它们是否为同一个对象。 ... [详细]
author-avatar
青岛新侨妙妙
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有