一、HotSpot算法细节

  1、根节点枚举:所有的收集器在根节点枚举的时候,必须暂停用户线程,同时要保证一致性的快照中得以进行。一致性:整个枚举期间执行子系统看起来就像是冻结在某一个时间点上,不会出现分析过程中,根节点的对象应用关系还在不断变化的情况。

  2、安全点:用户程序执行到某一些位置的时候,才能够暂停下来进行垃圾回收。一般安全点的产生,只有在指令序列复用。垃圾收集的时候,所有线程跑到最近的安全点:抢先式中断和主动式中断。

  3、安全区域:这样的方式似乎解决停顿用户线程,但是如果程序“不执行”的话,程序也就没有分配处理器的时间,这样也就没有响应虚拟机的中断请求,这种情况,必须引入安全区域来解决问题。

  4、记忆集与卡表:记忆集:用于记录从非收集区域指向收集区域的指针集合的抽象数据结构。记忆集是一种比较“抽象”的数据结构,抽象的意思是只定义了记忆集的行为意图,并没有定义其行为的具体实现。卡表是记忆集的一种具体实现。

  5、写屏障:写屏障技术来维护卡表状态的。

  6、并发的可达性分析:解决并发扫描的对象消失问题,产生了两种解决方案:增量更新和原始快照。所谓的原始快照:当灰色对象要删除指向的白色对象的引用关系时,将要删除的引用记录下来,在并发扫描结束之后,再将这些记录过的引用关系的灰色对象为根,重新扫描一次、PS:也就是说无论引用关系是否删除,都需要按照刚刚开始扫描那一刻的对象图快照进行搜索。

二、低延迟垃圾收集器

  衡量垃圾收集器最重要的三项指标:内存占用、吞吐量、延迟。其中延迟被誉为垃圾收集器最受到重视的性能指标。只有Shenandoah和ZGC属于低延迟垃圾收集器,并且实现垃圾收集的停顿时间不超过10毫秒,只有初始标记、最终标记这些阶段有短暂的停顿,停顿时间为固定的,与堆的容量、堆的数量没有正比例关系。

  1、Shenandoah收集器:是最“孤独”的一个。Shenandoah收集器的目标是能够在任何的堆内存大小下都能够可以把垃圾收集的停顿时间控制在10毫秒以内。同时与G1一样的是,Shenandoah收集器使用基于Region的堆内存布局,和G1不同的是,它只是并发的整理算法,但是不能和用户线程并发。G1收集器中使用的记忆集,消耗了大量的内存和计算资源。所以在Shenandoah收集器中抛弃了这种方式,改用“连接矩阵”来记录跨Region的引用关系。收集器的工作流程分为以下九个阶段:1、初始标记。2、并发标记。3、最终标记。4、并发清理。5、并发回收。6、初始引用更新。7、并发引用更新。8、最终引用更新。9、并发清理。

  Shenandoah收集器用来支持并行整理的核心概念 -- Brooks Pointer。转发指针分散的存放在每一个对象头前面。

  2、ZGC收集器:具有实验性质的低延迟垃圾收集器,不设分代,仅使用读屏障、染色指针[直接将少量额外的信息存储到指针]、内存多重映射来实现标记 - 整理算法。与Shenandoah、G1收集器不同的是,ZGC采用的基于Region的堆内存布局具有动态性,设置了大、中、小三类容量。需要注意的是,因为大型的Region内存分配在ZGC的实现中是不会重新分配的,因为复制大对象的代价非常的昂贵。

  接下来介绍一下ZGC的核心问题---并发整理算法,具有标志性的设计,采用了染色指针技术。ZGC直接将标记信息记到了引用对象的指针上,从而变成了遍历“引用图”来标记“引用”了。把染色指针中的标志位看做是地址的分段符,将不同的地址段都映射到同一个物理内存空间,经过多重映射转换后,使用染色指针可以正常进行寻址。ZGC的多重映射是采用染色指针技术的伴生产物,并不是专门为了实现其他的某种特性需求而去做的。

  ZGC收集器的工作流程:1、并发标记。2、并发预备重分配。3、并发重分配。4、并发重映射。

  当对象处于重分配中,用户线程在这个时候访问了此对象,则该访问会被预置的内存屏障截获,同时根据Region的转发表将访问转发到新复制的对象上,同时修正更新该引用的值,使其指向新的对象,ZGC将这种行为称为指针的“自愈能力”。

  巧妙地不止这个,还有并发重映射,重映射所要做的是修正整个堆中指向重分配集中旧对象的所有引用,但并不是一个迫切去完成的任务,之所以重映射这些旧引用是为了不变慢,所以说这个并不是很迫切,于是,巧妙地将并发重映射阶段做的工作,合并到了下一次垃圾收集循环中的并发标记阶段去完成。因此,基于上述过程,ZGC收集器和Shenandoah收集器做到了几乎可以在整个收集过程并发。

  ZGC收集器有一个技术优点:支持“NUMA-Aware”的内存分配,NUMA是为多处理器或者是多核处理器的计算机所设计的内存架构。

额外的知识点:

1、内存屏障:

2、虚拟内存映射技术:

 

Java虚拟机(JVM):第五幕:自动内存管理 - HotSpot算法细节以及低延迟垃圾收集器的更多相关文章

  1. 深入理解Java虚拟机之读书笔记一 自动内存管理机制

    一.运行时数据区域 1.程序计数器是线程的私有空间,每个线程都有.针对线程执行的是Java代码还是Native代码有两种取值,Java代码时:虚拟机字节码指令的地址:Native代码时:计数值为Und ...

  2. JVM 低延迟垃圾收集器 Shenandoah 和 ZGC

    本文部分摘自<深入理解 Java 虚拟机第三版> 概述 衡量垃圾收集器的三项指标分别是:内存占用.吞吐量和延迟.这三者共同构成一个"不可能三角",即一款优秀的收集器最多 ...

  3. Java自动内存管理机制学习(二):垃圾回收器与内存分配策略

    备注:本文引自<深入理解Java虚拟机第二版>仅供参考 图片来自:http://csdn.net/WSYW126 垃圾收集器与内存分配策略 概述 GC要完成3件事: 哪些内存需要回收? 什 ...

  4. JAVA之自动内存管理机制

    一.内存分配 1.JVM体系结构 2.运行时数据区域 3.内存分配二.内存回收 1.垃圾收集算法 2.垃圾收集器三.相关参考一.内存分配JVM体系结构 在了解自动内存管理的内存分配之前,我们先看下JV ...

  5. JVM | 第1部分:自动内存管理与性能调优《深入理解 Java 虚拟机》

    目录 前言 1. 自动内存管理 1.1 JVM运行时数据区 1.2 Java 内存结构 1.3 HotSpot 虚拟机创建对象 1.4 HotSpot 虚拟机的对象内存布局 1.5 访问对象 2. 垃 ...

  6. [深入理解Java虚拟机]<自动内存管理>

    Overview 走近Java:介绍Java发展史 第二部分:自动内存管理机制 程序员把内存控制的权利交给了Java虚拟机,从而可以在编码时享受自动内存管理.但另一方面一旦出现内存泄漏和溢出等问题,就 ...

  7. JVM自动内存管理-Java内存区域与内存溢出异常

    摘要: JVM内存的划分,导致内存溢出异常的可能区域. 1. JVM运行时内存区域 JVM在执行Java程序的过程中会把它所管理的内存划分为以下几个区域: 1.1 程序计数器 程序计数器是一块较小的内 ...

  8. JVM自动内存管理机制——Java内存区域(下)

    一.虚拟机参数配置 在上一篇<Java自动内存管理机制——Java内存区域(上)>中介绍了有关的基础知识,这一篇主要是通过一些示例来了解有关虚拟机参数的配置. 1.Java堆参数设置 a) ...

  9. JVM自动内存管理机制——Java内存区域(上)

    一.JVM运行时数据区域概述 Java相比较于C/C++的一个特点就是,在虚拟机自动内存管理机制的帮助下,我们不需要为每一个操作都写像C/C++一样的delete/free代码,所以也不容易出现内存泄 ...

  10. Java虚拟机笔记(五):JVM中对象的分代

    为什么要分代 为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用, ...

随机推荐

  1. 手写数字识别系统Python+CNN卷积神经网络算法【完整代码】

    一.介绍 手写数字识别系统,使用Python语言,基于TensorFlow搭建CNN卷积神经网络算法对数据集进行训练,最后得到模型,并基于FLask搭建网页端界面,基于Pyqt5搭建桌面端可视化界面. ...

  2. AcWing 第87场周赛题解

    T1 移动棋子 算出数值为 \(1\) 的点离 \((3, 3)\) 的距离即可. #include <iostream> #include <cstring> #includ ...

  3. 基于ChatGPT上线《你说我猜》小游戏

    摘要 AIGC.GPT.休闲小游戏三者可以怎么结合? AIGC.GPT与小游戏的结合为游戏体验带来了新的可能性.AIGC(Artificial Intelligence Game Content)作为 ...

  4. 图像分割_评价指标_PSNR峰值信噪比和SSIM结构相似度

    PSNR psnr是"Peak Signal to Noise Ratio"的缩写,即峰值信噪比,是一种评价图像的客观标准. 为了衡量经过处理后的影像品质,我们通常会参考PSNR值 ...

  5. 你知道.NET的字符串在内存中是如何存储的吗?

    毫无疑问,字符串是我们使用频率最高的类型.但是如果我问大家一个问题:"一个字符串对象在内存中如何表示的?",我相信绝大部分人回答不上来.我们今天就来讨论这个问题. 一.字符串对象的 ...

  6. Variable 'xxxx' is accessed from within inner class, needs to be final or effectively final-Lambda 表达式的变量与作用域

    问题的原因 问题代码: public static void main(String[] args) { Integer sum = 0; Integer count = 0; List<Int ...

  7. 王道oj/problem11(函数调用中实现指针的传递)

    网址:http://oj.lgwenda.com/prblem/11 思路:函数中的j=&i,为i的地址 *j可以从地址访问,从而改变i的值 代码: #define _CRT_SECURE_N ...

  8. [Python]数组基础

    在python中,一般使用列表表示数组.例如: 一维数组 arr1 = [1,2,3,4] 二维数组 arr2 = [[1,2,3,4],[5,6,7,8]] 数组的常用操作 追加 利用append( ...

  9. Programming abstractions in C阅读笔记p111-p113: boilerplate

    <Programming Abstractions In C>学习第47天,p111-p113,总结如下: 一.技术总结 1.boilerplate /* * File: random.h ...

  10. Java日志系列:Log4j使用和原理分析

    目录 一.简介 二.使用 三.日志级别 四.组件说明 Loggers Appenders Layouts 五.配置 加载初始化配置 配置文件加载 查看日志记录器的详细信息 六.Layout的格式 七. ...