JVM是如何解决跨代引用的?

这篇具有很好参考价值的文章主要介绍了JVM是如何解决跨代引用的?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

跨代引用问题

假如要现在进行一次只局限于新生代区域内的收集(Minor gc),但新生代的对象1在老年代中被引用,为了找出该区域(新生代)中所有的存活对象,不得不在固定的gc roots之外,在额外遍历整个老年代中所有对象来确保可达性分析结果的正确性。
遍历整个老年代所有对象的方案虽然可行,但是会给内存回收带来很大的性能负担。

实时上并不是只有新生代、老年代才有跨代引用的问题,所有涉及部分区域手机行为的垃圾收集器,典型的如G1、ZGC收集器,都会面临同样的问题。

如何解决跨代引用

先说结论,JVM是使用 写屏障 + 卡表 解决的。

  • 首先,跨代引用是少数的,例如:某个新生代对象存在跨代引用,由于老年代对象难以消亡,就会导致新生代对象在收集时同样得已存活,进而在年龄增长之后晋升到老年代中了。
  • 所以就不用为了少量的跨代引用扫描整个老年代,只需要在新生代建立一个全局的数据结构(该结构被称为 记忆集,Rember Set),标识出老年代的哪一块内存存在跨代引用,此后发生minor gc时,只有包含了跨代引用的小块内存里的对象才会被加入gc root进行扫描。
  • 个人理解,card table是用来划分老年代的,即把老年代划分多个大小相等的连续区域,而Rember set中记录了卡表的位置。

记忆集(Remembered Set)

一种记录 从非收集区域(如老年代) 指向 收集区域(如年轻代)的指针集合的抽象数据结构,在对象层面来说就是非收集区域对收集区域对象的引用记录。
它存放在收集区域,比如在新生代里面存放着老年代对新生代的每一个引用,这样在收集新生代的时候,我们就可以根据记忆集知道哪些对应被老年代对象引用了,不能回收,这就解决了跨代引用过的问题。

记忆集根据记录的精度可以分三类实现方式:

  • 字长精度:记录的是老年代指向新生代地址。
  • 对象精度:记录的是老年代引用的新生代对象。
  • 卡精度:记录的是新生代一段地址是否存在被老年代引用的记录

卡表

是以第三种卡精度的方式实现的记忆集,也是目前最常用的方式。记忆集是抽象的概念,而卡表就是记忆集的一种具体实现。

卡表最简单的形式可以是一个字节数组,HotSpot就是这样实现的。
CARD_TABLE [this address >> 9] = 0;

把地址的值右移9位相当于除于512就是卡表索引,每字节512为一组对应卡表同一个元素,一组就是一个卡页,如果这个卡页中只要有一个对象被其他区域对象所引用,对应卡表元素的值就变成1,也就是所谓的元素变脏。

在垃圾回收时,只要筛选出卡表中变脏的元素,就能轻易得出哪些卡页对应的内存包含跨代指针,把他们加入GC Rootsz中一并扫描。

写屏障

可以看成是虚拟机层面在“引用类型字段赋值”这个动作的AOP切面,引用对象赋值的时候产生一个环形通知,进行一些额外的处理,这样就是引用对象赋值这个操作都在写屏障的覆盖范围内,赋值前的写屏障叫写前屏障,赋值后的写屏障叫写后屏障。
卡表的更新,就是通过写屏障写入的。文章来源地址https://www.toymoban.com/news/detail-839719.html

到了这里,关于JVM是如何解决跨代引用的?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JVM虚拟机(五)强引用、软引用、弱引用、虚引用

    引文: 在 Java 中一共存在 4 种引用:强、软、弱、虚。它们主要指的是,在进行垃圾回收的时候,对于不同的引用垃圾回收的情况是不一样的。下面我们就一起来看一下这 4 种引用。 强引用 :只有所有 GC Root 对象都不通过【强引用】引用该对象,该对象才能被垃圾回收。

    2024年04月15日
    浏览(52)
  • JVM 对象引用类型

    对象引用类型分为强引用、软引用、弱引用和虚引用。 强引用         声明对象时虚拟机生成的引用,是指在程序代码之中普遍存在的引用赋值。强引用环境下,垃圾回收时需要严格判断当前对象是否被强引用,如果被强引用,则不会被垃圾回收,当内存空间不足的时候

    2024年02月09日
    浏览(47)
  • JVM 引用的分类

    引用计数算法和根搜索算法都需要通过判断引用的方式判断对象是否可回收。 JDK1.2 之前,Java 中引用的定义很传统:如果 reference 类型的数据存储的数值代表的是另一块内存的起始地址,就称这块内存代表一个引用。 在 JDK 1.2 之后,Java 将引用分成四种,按照引用强度从高到

    2024年04月22日
    浏览(59)
  • JVM之强软弱虚引用

    在Java虚拟机(JVM)中,有几种不同类型的引用,它们分别是:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)和引用队列(Reference Queue)。这些引用类型提供了对对象的不同级别的引用,用于垃圾回收和内存管理。 1. 强引用

    2024年02月09日
    浏览(47)
  • JVM 四种引用和使用场景

    一、前言 在JDK 1.2之后,Java对引用的概念进行了扩充,将引用分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)四种,Java 4种引用的级别由高到低依次为:强引用 软引用 弱引用 虚引用。 Java垃圾回收器会优先清理可达强度

    2024年01月19日
    浏览(47)
  • JVM7:垃圾回收是什么?从运行时数据区看垃圾回收到底回收哪块区域?垃圾回收如何去回收?垃圾回收策略,引用计数算法及循环引用问题,可达性分析算法

    在Java中,垃圾回收(Garbage Collection,简称GC),是自动管理内存的机制。它负责检测不再使用的对象,并释放它们所占用的内存,以供其他对象使用。 JVM内存模型认识的差不多了,就应该思考,什么样的内存模型适合什么样的GC策略,包括垃圾回收为什么会出现。实际上,很多

    2024年02月11日
    浏览(36)
  • Java虚拟机(JVM):引用计数算法

    我们学习了Java内存运行时区域的各个部分,其中程序计数器、虚拟机栈、本地方法栈3个区域随线程而生,随线程而灭。栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作。每一个栈帧中分配多少内存基本上是在类结构确定下来就已知的,因此这几个区域

    2024年02月12日
    浏览(42)
  • 49天精通Java,第34天,finalize、引用计数、JVM停止复制、JVM即时编译器

    在Java中,finalize()是一个Object类的方法,用于在对象被垃圾收集器回收之前执行一些清理操作。当一个对象成为垃圾时,它的finalize()方法会被自动调用。 finalize()方法的语法格式如下:

    2024年02月07日
    浏览(48)
  • 【JVM篇】ThreadLocal中为什么要使用弱引用

    ThreadLocal可以在线程中存放线程的本地变量,保证数据的线程安全 ThreadLocal是这样子保存对象的: 在每个线程中,存放了一个ThreadLocalMap对象,本质上就是一个数组实现的哈希表,里面存放多个Entry对象 每个Entry对象继承自弱引用,内部存放ThreadLocal对象,同时用强引用,引用

    2024年02月20日
    浏览(54)
  • 【Java】图解 JVM 垃圾回收(一):GC 判断策略、引用类型、垃圾回收算法

    垃圾 是指运行程序中 没有任何引用指向的对象 ,需要被回收。 内存溢出 :经过垃圾回收之后,内存仍旧无法存储新创建的对象,内存不够溢出。 内存泄漏 :又叫 “ 存储泄漏 ”,对象不会再被程序使用了,但是 GC 又不能回收它们。例如:IO 流不适用了但是没有被 Close、

    2024年02月19日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包