1 从原理聊JVM(一):染色标记和垃圾回收算法-德赢Vwin官网 网
0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

从原理聊JVM(一):染色标记和垃圾回收算法

京东云 来源:jf_75140285 作者:jf_75140285 2024-08-20 15:25 次阅读

导读

JAVA简单易用的特性,能够让研发人员在不了解JVM的底层运行机制的情况下依旧能够编写出功能完善的代码。

但是对JVM的理解,是一个程序员普通和优秀的分水岭。全面地了解JVM的工作原理,能够更好地优化自己的代码,并解决一些潜在的性能问题。

本文及后续文章将从原理聊起,对JVM的内存分配、GC、编译等知识进行分析和总结。

1 JVM运行时内存划分

1.1 运行时数据区域

wKgaombERMKAIkVjAAHROjCUdGM843.png



方法区

属于共享内存区域,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。运行时常量池,属于方法区的一部分,用于存放编译期生成的各种字面量和符号引用。

JDK1.8之前,Hotspot虚拟机对方法区的实现叫做永久代,1.8之后改为元空间。二者区别主要在于永久代是在JVM虚拟机中分配内存,而元空间则是在本地内存中分配的。很多类是在运行期间加载的,它们所占用的空间完全不可控,所以改为使用本地内存,避免对JVM内存的影响。根据《Java虚拟机规范》的规定,如果方法区无法满足新的内存分配需求时,将抛出OutOfMemoryError异常。

线程共享,主要是存放对象实例和数组。如果在Java堆中没有内存完成实例分配,并且堆也无法再扩展时,Java虚拟机将会抛出OutOfMemoryError异常。PS:实际上写入时并不完全共享,JVM会为线程在堆上划分一块专属的分配缓冲区来提高对象分配效率。详见:TLAB

虚拟机栈

线程私有,方法执行的过程就是一个个栈帧从入栈到出栈的过程。每个方法在执行时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。如果线程入栈的栈帧超过限制就会抛出StackOverFlowError,如果支持动态扩展,那么扩展时申请内存失败则抛出OutOfMemoryError。

本地方法栈

和虚拟机栈的功能类似,区别是作用于Native方法。

程序计数器

线程私有,记录着当前线程所执行的字节码的行号。其作用主要是多线程场景下,记录线程中指令的执行位置。以便被挂起的线程再次被激活时,CPU能从其挂起前执行的位置继续执行。唯一一个在 Java 虚拟机规范中没有规定任何 OutOfMemoryError 情况的区域。注意:如果线程执行的是个java方法,那么计数器记录虚拟机字节码指令的地址。如果为native(底层方法),那么计数器为空。

1.2 对象的内存布局

在 HotSpot 虚拟机中,对象分为如下3块区域:

•对象头(Header)运行时数据:哈希码、GC分代年龄、锁状态标志、偏向线程ID、偏向时间戳等。类型指针:对象的类型元数据的指针,如果对象是数据,还会记录数组长度。

•对象实例数据(Instance Data)包含对象真正的内容,即其包括父类所有字段的值。

•对齐填充(Padding)对象大小必须是是8字节的整数倍,所以对象大小不满足这个条件时,需要用对齐填充来补齐。

2 标记的方法和流程

2.1 判断对象是否需要被回收

要分辨一个对象是否可以被回收,有两种方式:引用计数法可达性算法

•引用计数法就是在对象被引用时,计数加1,引用断开时,计数减1。那么一个对象的引用计数为0时,说明这个对象可以被清除。这个算法的问题在于,如果A对象引用B的同时,B对象也引用A,即循环引用,那么虽然双方的引用计数都不为0,但如果仅仅被对方引用实际上没有存在的价值,应该被GC掉。

•可达性算法通过引用计数法的缺陷可以看出,从被引用一方去判定其是否应该被清理过于片面,所以我们可以通过相反的方向去定位对象的存活价值:一个存活对象引用的所有对象都是不应该被清除的(Java中软引用或弱引用在GC时有不同判定表现,不在此深究)。这些查找起点被称为GC Root。

2.2 哪些对象可以作为GC Root呢?

1.JAVA虚拟机栈中的本地变量引用对象

2.方法区中静态变量引用的对象

3.方法区中常量引用的对象

4.本地方法栈中JNI引用的对象

2.3 快速找到GC Root - OopMap

栈与寄存器都是无状态的,保守式垃圾收集会直接线性扫描栈,再判断每一串数字是不是引用,而HotSpot采用准确式垃圾收集方式,所有对象都存放在OopMap(Ordinary Object Pointer)中,当GC发生时,直接从这个map中寻找GC Root。

将GC Root存放到OopMap有两个触发时间点:

1.类加载完成后,HotSpot就会把对象内什么偏移量上是什么类型的数据计算出来。

2.即时编译过程中,也会在特定的位置记录下栈里和寄存器里哪些位置是引用。

2.4 更新OopMap的时机 - 安全点

导致OopMap更新的指令非常多,所以HotSpot只在特定位置进行记录更新,这些位置叫做安全点。安全点位置的选取的标准是:“是否具有让程序长时间执行”。比如方法调用、循环跳转、异常跳出等等。

2.5 可达性分析过程

三色标记法

白色:表示垃圾回收过程中,尚未被垃圾收集器访问过的对象,在可达性分析开始阶段,所有对象都是白色的,即不可达。

黑色:被垃圾收集器访问过的对象,且这个对象所有的引用均扫描过。黑色的对象是安全存活的,如果其他对象被访问时发现其引用了黑色对象,该黑色对象也不会再被扫描。

灰色:被垃圾收集器访问过的对象,但这个对象至少有一个引用的对象没有被扫描过。那么标记阶段就是从GC Root的开始,沿着其引用链将每一个对象从白色标记为灰色最后标记为黑色的过程。

标记过程中不一致问题

由于这个阶段是层层递进的标记,所以过程中难免出现不一致的情况导致原本是黑色的对象被标记为白色,比如,当前扫描到B对象了,C对象尚未被访问时,标记情况如下:

wKgZombERMOAO-txAAAsjteoOf8539.png

那么如果这时A对象取消了对B对象的引用,而GC Root增加了对C对象的引用,GC Root作为黑色标记不会再次被扫描,那么C对象在标记阶段结束后仍然会保持白色,就会被清除掉。

wKgaombERMOAFsbkAAA5d9WuaBM141.png

解决方式

增量更新

当黑色对象增加了对白色对象的引用时,将其从黑色改为灰色,等并发标记阶段结束后,从GC Root开始顺着对象图再将灰色对象重新扫描一次,这个扫描过程会STW,不会再次产生不一致问题。CMS就采用了这种方式。

原始快照(SATB)

当灰色对象删除了白色对象的引用时,将其记录在线程独占的SATB Queue中,让其在标记阶段结束后被再次扫描。 G1、Shenandoah采用了这种方式。

示例

我们通过一个例子来展示两种处理方式的不同,比如正常标记到对象A时,将其标记为灰色:

wKgZombERMSAGd95AAApxOmPhtU488.png

此时,用户线程发生如下行为:

1.GC Root直接引用了C

2.A取消了引用B

理论上,C仍然是可达对象,不应被清除,而B不可达,应当被清除。

wKgZombERMWAfE91AAA2q4bUlHw904.png

增量更新会记录行为1,将GC Root标记为灰色,B不能访问到被标记为可以回收

wKgaombERMmASFT9AAA17Jd0In4144.png

等到重新标记阶段再次访问灰色的GC Root,顺序将GC Root和C标记为黑色:

wKgZombERMyAAn8fAAA2XWh-BpE186.png

而原始快照会记录行为2,将发生引用变化的对象全部记录下来,等到重新标记阶段再次访问这些灰色,将其标记为黑色并顺着对象图扫描。

wKgZombERM2AMeh_AABeptJlui4287.png

那么最终B作为浮动垃圾就被保存下来了,只能等到下一次GC时才能被回收。

3 分代模型

3.1 分代假说

弱分代假说(WeakGenerationalHypothesis):绝大多数对象都是朝生夕灭的。 强分代假说(StrongGenerationalHypothesis):熬过越多次垃圾收集过程的对象就越难以消亡。 跨代引用假说(IntergenerationalReferenceHypothesis):跨代引用相对于同代引用来说仅占极少数。

上述假说是根据实际经验得来的,由此垃圾收集器通常分为“年轻代”和“年老代”:

•年轻代用来存放不断生成且生命周期短暂的对象,收集动作相对高频

•年老代用来存放经历多次GC仍然存活的对象,收集动作相对低频

3.2 空间分配担保

如果在GC后新生代存货对象过多,Survivor无法容纳,那么将会把这些对象直接送入年老代,这就叫年老代进行了“分配担保”。 为了保证年老代能够足够空间容纳这些直接晋升的对象,在发生Minor GC之前,虚拟机必须先检查年老代最大可用的连续空间,如果大于新生代所有对象总空间或者历次晋升的平均大小,就会进行MinorGC,否则将进行FullGC以同时清理年老代。

3.3 记忆集和卡表

记忆集是一种用于记录从非收集区域指向收集区域的指针集合的抽象数据结构。

记忆集的作用

新生代发生垃圾收集时(Minor GC),如果想确定这个新生代对象是否被年老代的对象引用,则需要扫描整个年老代,成本非常高。

如果我们能知道哪一部分年老代可能存在对新生代的引用,就可以降低扫描范围。

所以我们可以在新生代建立一个全局数据结构叫“记忆集(Remembered Set)”,这个结构把年老代分为若干个小块,标记了哪些小块内存中存在引用了新生代对象的情况,等到Minor GC时,只扫描这部分存在跨代引用的内存块即可。虽然在对象变化时增加了维护记忆集的成本,但相比垃圾收集时扫描整个年老代来说是值得的。

JVM通常在对象增加引用前设置写屏障判断是否发生跨代引用,如果有跨代情况,则更新记忆集。

卡表

实现记忆集时,可以有不同精度的粒度:可以指向内存地址,也可以指向某个对象,或者指向某一块内存区域。精度越低,维护成本越低。指向某一块内存区域的实现方式就是“卡表”。卡表通常就是一个byte数组,数组中每一个元素代表某一块内存,其值是1或者0:当发生跨代引用时,就表示该元素“dirty”了,那么将将其设置为1,否则就是0。

wKgaombERM6AEETyAABsrdTtdOc939.png

4 垃圾回收算法

4.1 标记-清除(Mark-Sweep)

GC分为两个阶段,标记和清除。首先标记所有可回收的对象,在标记完成后统一回收所有被标记的对象。

缺点是清除后会产生不连续的内存碎片。碎片过多会导致以后程序运行时需要分配较大对象时,无法找到足够的连续内存,而不得已再次触发GC。

wKgZombERM-ATf12AAFWomdafMs003.png

4.2 标记-复制(Mark-Copy)

将内存按容量划分为两块,每次只使用其中一块。当这一块内存用完了,就将存活的对象复制到另一块上,然后再把已使用的内存空间一次清理掉。

这样使得每次都是对半个内存区回收,也不用考虑内存碎片问题,简单高效。

wKgaombERNCASAhcAAFW9rWl_iY234.png

缺点需要两倍的内存空间。

一种优化方式是使用eden和survivior区,具体步骤如下:

eden和survivior区默认内存空间占比为8:1:1,同一时间只使用eden区和其中一个survivior区。标记完成后,将存活对象复制到另一个未使用的survivior区(部分年龄过大的对象将升级到年老代)。

这种做法,相比普通的两块空间的标记复制算法来说,只有10%的内存空间浪费,而这样做的原因是:大部分情况下,一次young gc后剩余的存活对象非常少

wKgaombERNWAT6NeAABnHaX5duM018.png

4.3 标记-整理(Mark-Compact)

标记-整理也分为两个阶段,首先标记可回收的对象,再将存活的对象都向一端移动,然后清理掉边界以外的内存。

wKgaombERNiAMnmqAAJ6Rs95j3c612.png

此方法避免标记-清除算法的碎片问题,同时也避免了复制算法的空间问题。 一般年轻代中执行GC后,会有少量的对象存活,就会选用复制算法,只要付出少量的存活对象复制成本就可以完成收集。

而年老代中因为对象存活率高,用标记复制算法时数据复制效率较低,且空间浪费较大。所以需要使用标记-清除或者标记-整理算法来进行回收。

所以通常可以先使用标记清除算法,当碎片率高时,再使用标记整理算法。

5 最后

本篇介绍了JVM中垃圾回收器相关的基础知识,后续会深入介绍CMS、G1、ZGC等不同垃圾收集器的运作流程和原理,欢迎关注。



系列文章:

从原理聊JVM(一):染色标记和垃圾回收算法

从原理聊JVM(二):从串行收集器到分区收集开创者G1

从原理聊JVM(三):详解现代垃圾回收器Shenandoah和ZGC

从原理聊JVM(四):JVM中的方法调用原理

从原理聊JVM(五):JVM中的编译过程和优化手段

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表德赢Vwin官网 网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 算法
    +关注

    关注

    23

    文章

    4607

    浏览量

    92820
  • 内存
    +关注

    关注

    8

    文章

    3019

    浏览量

    74000
  • JVM
    JVM
    +关注

    关注

    0

    文章

    158

    浏览量

    12220
收藏 人收藏

    评论

    相关推荐

    JVM xmx, xms等内存相关参数合理性设置

    作者:京东零售 刘乐 上篇文章说到JVM垃圾回收算法的两个优化标的:吞吐量和停顿时长,并提到这两个优化目标是有冲突的。那么有没有可能提高吞
    的头像 发表于 10-10 14:42 455次阅读

    智能回收箱的功能和使用步骤介绍

    智能回收箱是现代城市环保与资源循环利用领域的项创新技术,它通过集成各种智能化功能,提高了垃圾回收的效率和准确性,促进了垃圾分类与减量。随着
    的头像 发表于 09-23 14:34 638次阅读
    智能<b class='flag-5'>回收</b>箱的功能和使用步骤介绍

    聊聊JVM如何优化

    首先应该明确的是JVM调优不是常规手段,JVM的存在本身就是为了减轻开发对于内存管理的负担,当出现性能问题的时候第时间考虑的是代码逻辑与设计方案,以及是否达到依赖中间件的瓶颈,最后才是针对J
    的头像 发表于 08-05 17:49 463次阅读
    聊聊<b class='flag-5'>JVM</b>如何优化

    RFID智慧环卫护航城市垃圾精细化管理

    。而RFID技术作为物联网技术的重要组成部分,正在改变着城市的管理方式和效率,为智慧城市的发展提供了强大支持。 为解决城市小区垃圾回收问题,采用 RFID技术 对城市垃圾进行回收与监管
    的头像 发表于 06-20 10:14 341次阅读
    RFID智慧环卫护航城市<b class='flag-5'>垃圾</b>精细化管理

    MK米客方德SD NAND的垃圾回收机制

    无人机在各个领域的应用日益广泛,航拍、物流配送到农业监测,无人机正逐渐成为我们生活中不可或缺的部分。作为种创新的存储芯片,SD NAND因其小巧的尺寸、高可靠性和高速接口,尤其适用于空间有限
    的头像 发表于 06-05 14:00 677次阅读
    MK米客方德SD NAND的<b class='flag-5'>垃圾</b><b class='flag-5'>回收</b>机制

    智能垃圾回收箱功能实验

    需要系统地介绍智能垃圾回收箱软件硬件设计完成后的设备运行状况,包括正常工作和问题调试。同时,也要描述当所有设备正常工作时智能垃圾回收箱的操作流程。01硬件模块的试验在智能
    的头像 发表于 05-24 08:10 442次阅读
    智能<b class='flag-5'>垃圾</b><b class='flag-5'>回收</b>箱功能实验

    垃圾清运以及垃圾处理“神器”让垃圾清运更高效。

    随着城市功能的不断丰富,城市管理工作也粗放到精细、纯人工管理到数字化应用逐渐转变。近日,某小区垃圾满溢监测“神器”上线,能够实时监控区内果皮箱的数量、位置、垃圾量情况,让
    的头像 发表于 05-13 09:37 378次阅读
    <b class='flag-5'>垃圾</b>清运以及<b class='flag-5'>垃圾</b>处理“神器”让<b class='flag-5'>垃圾</b>清运更高效。

    垃圾中转站无人值守物联网解决方案

    收集点的垃圾,进行分类分拣与处理回收,随后再转运到焚烧厂、填埋场或回收站等进行最终处理。随着各种智能装备的加入,如压滤设备、污水处理设备、废气净化设备等,为垃圾中转提供高效率低成本的工
    的头像 发表于 04-19 11:22 697次阅读
    <b class='flag-5'>垃圾</b>中转站无人值守物联网解决方案

    智能垃圾回收箱系统软件设计

    智能垃圾回收箱自动分拣、智能感知智能垃圾回收箱是物联网设备,通常支持联网和与手机应用程序进行交互等功能。这些功能需要可靠的云平台支持,因此选择合适的云平台至关重要。物联网平台选择机智云
    的头像 发表于 04-19 08:10 528次阅读
    智能<b class='flag-5'>垃圾</b><b class='flag-5'>回收</b>箱系统软件设计

    智能垃圾回收箱控制系统硬件设计

    智能高效远程控制智能垃圾回收箱控制系统硬件部分的选型与设计是整个产品的基础,所有功能的实现都要围绕其进行开发。本章对智能垃圾回收箱控制系统的硬件进行详细设计。智能
    的头像 发表于 04-13 08:10 834次阅读
    智能<b class='flag-5'>垃圾</b><b class='flag-5'>回收</b>箱控制系统硬件设计

    智能垃圾回收箱及其控制系统

    智能高效远程控制智能垃圾回收箱本文设计了基于机械传动、嵌入式系统和物联网技术的智能垃圾回收箱及控制系统,包括结构、硬件和软件设计,以及基于机智云后台服务器的操作系统,实现了用户信息识
    的头像 发表于 04-13 08:10 1207次阅读
    智能<b class='flag-5'>垃圾</b><b class='flag-5'>回收</b>箱及其控制系统

    智能垃圾回收箱控制系统硬件设计-机智云

    、精度以及输出形式。量程大小需要考虑多方条件。 根据经验,称重传感器般工作在 30%⁓70%量程范围内,若在使用时有较大冲击,称重需要扩大量程。本文设计的智能垃圾回收箱,主要回收
    发表于 04-09 17:37

    基于机智云物联网平台的智能垃圾回收箱与控制系统研究

    款基于机械传动、嵌入式系统和物联网技术的智能垃圾回收箱及控制系统。结合功能需求设计了结构方案,包括尺寸、开关门、防夹手机和称重结构等;选型硬件包括主控制器、电源、称重检测、显示、电机控制、语音提示
    发表于 04-09 17:25

    AI垃圾溢出识别摄像机

    随着城市化进程的加快,垃圾处理成为城市管理中的项重要工作。然而,垃圾桶溢出现象经常发生,给城市环境卫生和市民生活带来不便。为了解决这问题,AI
    的头像 发表于 03-13 11:04 466次阅读
    AI<b class='flag-5'>垃圾</b>溢出识别摄像机

    餐厨垃圾设备智能监控运维系统解决方案

    在当今社会,随着科技的不断进步,人们对于环保和资源利用的意识也在不断提高,其中餐厨垃圾的处理回收受到人们的广泛关注。它是种专门用于处理餐厨垃圾的设备,通过对
    的头像 发表于 01-09 16:32 455次阅读