热门标签 | 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)



推荐阅读
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • ElasticSearch 集群监控与优化
    本文详细介绍了如何有效地监控 ElasticSearch 集群,涵盖了关键性能指标、集群健康状况、统计信息以及内存和垃圾回收的监控方法。 ... [详细]
  • 并发编程 12—— 任务取消与关闭 之 shutdownNow 的局限性
    Java并发编程实践目录并发编程01——ThreadLocal并发编程02——ConcurrentHashMap并发编程03——阻塞队列和生产者-消费者模式并发编程04——闭锁Co ... [详细]
  • 本文将详细探讨 Java 中提供的不可变集合(如 `Collections.unmodifiableXXX`)和同步集合(如 `Collections.synchronizedXXX`)的实现原理及使用方法,帮助开发者更好地理解和应用这些工具。 ... [详细]
  • 软件工程课堂测试2
    要做一个简单的保存网页界面,首先用jsp写出保存界面,本次界面比较简单,首先是三个提示语,后面是三个输入框,然 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 主板IO用W83627THG,用VC如何取得CPU温度,系统温度,CPU风扇转速,VBat的电压. ... [详细]
  • 本文探讨了如何通过预处理器开关选择不同的类实现,并解决在特定情况下遇到的链接器错误。 ... [详细]
  • 本文探讨了为何相同的HTTP请求在两台不同操作系统(Windows与Ubuntu)的机器上会分别返回200 OK和429 Too Many Requests的状态码。我们将分析代码、环境差异及可能的影响因素。 ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • 深入解析Spring启动过程
    本文详细介绍了Spring框架的启动流程,帮助开发者理解其内部机制。通过具体示例和代码片段,解释了Bean定义、工厂类、读取器以及条件评估等关键概念,使读者能够更全面地掌握Spring的初始化过程。 ... [详细]
  • 在尝试使用C# Windows Forms客户端通过SignalR连接到ASP.NET服务器时,遇到了内部服务器错误(500)。本文将详细探讨问题的原因及解决方案。 ... [详细]
  • CentOS 6.8 上安装 Oracle 10.2.0.1 的常见问题及解决方案
    本文记录了在 CentOS 6.8 系统上安装 Oracle 10.2.0.1 数据库时遇到的问题及解决方法,包括依赖库缺失、操作系统版本不兼容、用户权限不足等问题。 ... [详细]
  • 本文介绍了在MacOS上通过Homebrew安装Anaconda3,并配置环境变量以实现不同Python版本之间的快速切换。同时,提供了详细的步骤来创建和管理多个Python环境。 ... [详细]
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社区 版权所有