当前位置: 首页 > news >正文

JVM:如果是你,你如何解决跨代引用的问题?(记忆集和卡集)

这部分内容主要是为了稍后介绍各款垃圾收集器时做前置知识铺垫,如果对这部分内容感到枯燥或者疑惑,可以先放下看,等后续遇到要使用它们的实际场景、实际问题时再结合问题,再回来阅读和理解。

记忆集和卡集

前面在分代收集理论那一节稍微讲到对象不是孤立的,对象之间存在跨代引用。如果还是不大明白,看我下面这个例子:老年代引用年轻代

public class ClassRoomLocalCache {// 静态变量 map,以及 map 中引用的 ClassRoom 类型变量大概熬过默认的 15 次垃圾收集,都会晋升到老年代private static final Map<String,ClassRoom> map = new ConcurrentHashMap<>();public static void addStudent(String classRoomId) {// ......// 运行时,新初始化了一个对象 Student ,对象实例假设在年轻代分配内存// 老年代引用年轻代map.get(classRoomId).getUsers().add(new Student("127", "李华", 22));}@Getterprivate static class ClassRoom {private String id;private String name;private Integer num;private List<Student> users;}@AllArgsConstructorprivate static class Student {private String id;private String name;private Integer age;}}

再回一下前面提到的经验法则三,为什么说跨代引用相对于同代引用来说仅占极少数?

因为存在互相引用关系的两个对象,是应该倾向于同时生存或者同时消亡的。例如上面程序中的这个例子(稍微结合例子解释下)

举个例子,如果某个新生代对象存在跨代引用,由于老年代对象难以消亡,该引用会使得新生代对象在收集时同样得以存活,进而在年龄增长之后晋升到老年代中,这时跨代引用也随即被消除了。 

其实上面说的只是一个经验法则或者说是理论,实际上并没有解决当需要在年轻代gc 时因可能存在跨在引用,为了找出该区域中的存活对象,不得不在固定的GC Roots之外,再额外遍历整个老年代中所有对象来确保可达性分析结果的正确性

事实上并不只是新生代、老年代之间才有跨代引用的问题,所有涉及部分区域收集(Partial GC)行为的垃圾收集器(G1、ZGC)都会面临相同的问题。

可以想一下,如果是你,你会怎么设计解决这个问题?

由于跨代引用占极少数,我想最简单的实现的就是维护一个对象数组,每当有老年代对象引用年轻代对象就把老年代对象存储到这个数组中,然后在年轻代收集时,把这个数组的对象一并加入到gc roots 中去进行扫描。

实际上,JVM 的设计者的思路也大概是这样,就是在收集区域(可以理是新生代)开辟一块小内存维护一个数据结构,这个抽象数据结构用于记录从非收集区域指向收集区域的指针集合,他们称为记忆集。

然而JVM 设计者并没有直接使用如上最简单的实现方案。这种记录全部含跨代引用对象的实现方案,无论是空间占用还是维护成本都相当高昂。而在垃圾收集的场景中,收集器只需要通过记忆集判断出某一块非收集区域是否存在有指向了收集区域的指针就可以了,并不需要了解这些跨代指针的全部细节。那设计者在实现记忆集的时候,他们选择更为粗犷的记录粒度来节省记忆集的存储和维护成本,也就是卡精度的实现方案。

对象精度:每个记录精确到一个对象,该对象里有字段含有跨代指针。 
卡精度:每个记录精确到一块内存区域,该区域内有对象含有跨代指针。

卡精度”所指的是用一种称为“卡表”(Card Table)的方式去实现记忆集,这也是目前最常用的一种记忆集实现形式,一些资料中甚至直接把它和记忆集混为一谈。前面定义中提到记忆集其实是一种“抽象”的数据结构,抽象的意思是只定义了记忆集的行为意图,并没有定义其行为的具体实现。卡表就是记忆集的一种具体实现,它定义了记忆集的记录精度、与堆内存的映射关系等。 (可以对比map 和HashMap)

卡表最简单的形式可以只是一个字节数组,而HotSpot虚拟机确实也是这样做的。以下这行代码是HotSpot默认的卡表标记逻辑:

CARD_TABLE [this address >> 9] = 0;

字节数组CARD_TABLE的每一个元素都对应着其标识的内存区域中一块特定大小的内存块,这个内存块被称作“卡页”(Card Page)。一般来说,卡页大小都是以2的N次幂的字节数,通过上面代码可以看出HotSpot中使用的卡页是2的9次幂,即512字节

img

一个卡页的内存中通常包含不止一个对象,只要卡页内有一个(或更多)对象的字段存在着跨代指针,那就将对应卡表的数组元素的值标识为1,称为这个元素变脏(Dirty),没有则标识为0。在垃圾收集发生时,只要筛选出卡表中变脏的元素,就能轻易得出哪些卡页内存块中包含跨代指针,把它们加入GC Roots中一并扫描。

相关文章:

JVM:如果是你,你如何解决跨代引用的问题?(记忆集和卡集)

这部分内容主要是为了稍后介绍各款垃圾收集器时做前置知识铺垫&#xff0c;如果对这部分内容感到枯燥或者疑惑&#xff0c;可以先放下看&#xff0c;等后续遇到要使用它们的实际场景、实际问题时再结合问题&#xff0c;再回来阅读和理解。 记忆集和卡集 前面在分代收集理论那…...

Python实现WOA智能鲸鱼优化算法优化卷积神经网络分类模型(CNN分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 鲸鱼优化算法 (whale optimization algorithm,WOA)是 2016 年由澳大利亚格里菲斯大学的Mirjalili 等提…...

使用 Qt 实现监听网页是否响应,导出 Excel 表

Qt 实现监听网页是否响应 要使用 Qt 实现监听网页是否响应&#xff0c;可以利用 QNetworkAccessManager 类来发送 HTTP 请求并处理响应。以下是一个示例代码&#xff1a; #include <QtNetwork>int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);// 创…...

Java通过JNI技术调用C++动态链接库的helloword测试

JNI调用原理 原理就不细说了&#xff0c;其实就是写个库给Java调&#xff0c;可以百度一下Java JNI&#xff0c;下面是HelloWorld代码测试 编写一个本地测试类 package com.my.study.cpp_jni;/*** 测试Java调用C库* <p>使用命令javac -h . NativeTest.java自动生成C头…...

Python爬虫所需的常用库

爬虫是指通过程序自动访问互联网上的各种网站&#xff0c;并从网站上抓取所需的数据。Python作为一门强大的编程语言&#xff0c;拥有丰富的库和工具&#xff0c;使得编写爬虫变得更加容易和高效。本文将介绍一些Python爬虫中常用的库&#xff0c;包括网络请求库、解析库、数据…...

Android Studio真机运行时提示“安装失败”

用中兴手机真机运行没问题&#xff0c;用Vivo运行就提示安装失败。前提&#xff0c;手机已经打开了调试模式。 报错 Android Studio报错提示&#xff1a; Error running app The application could not be installed: INSTALL_FAILED_TEST_ONLY 手机报错提示&#xff1a; 修…...

【C语言数据结构————————二叉树】

文章目录 文章目录 一、什么是树 树的定义 树的种类 树的深度 树的基本术语 二、满二叉树 定义 满二叉树的特点 三、完全二叉树 定义 特点 四、二叉树的性质 五、二叉树的存储结构 顺序存储结构 链式存储结构 六、二叉树的基本操作 七、二叉树的创建 八、二叉树…...

分组取每组数据的最大值和最小值的方法思路,为类似场景的数据分析提取提供思路,例如提取宗地内建筑的最高层数等可参考此方法思路

目录 一、实现效果 二、实现过程 1.读取并剔除无效数据 2.数据分组 3.提取最大值 4.提取最小值 三、总结 使用FME实现批量分组取每组数据的最大值和最小值&#xff0c;为类似场景的数据分析提取提供思路&#xff0c;例如提取宗地内建筑的最高层数等可参考此方法思路。关…...

MyBatis 反射工具箱:带你领略不一样的反射设计思路

反射是 Java 世界中非常强大、非常灵活的一种机制。在面向对象的 Java 语言中&#xff0c;我们只能按照 public、private 等关键字的规范去访问一个 Java 对象的属性和方法&#xff0c;但反射机制可以让我们在运行时拿到任何 Java 对象的属性或方法。 有人说反射打破了类的封装…...

Netty第三部

继续Netty第二部的内容 一、ChannelHandler 1、ChannelHandler接口 ChannelHandler是Netty的主要组件&#xff0c;处理所有的入站和出站数据的应用程序逻辑的容器&#xff0c;可以应用在数据的格式转换、异常处理、数据报文统计等 继承ChannelHandler的两个子接口&#xff…...

【C++入门篇】保姆级教程篇【下】

目录 一、运算符重载 1&#xff09;比较、赋值运算符重载 2&#xff09; 流插入留提取运算符重载 二、剩下的默认成员函数 1&#xff09;赋值运算符重载 2&#xff09;const成员函数 3&#xff09;取地址及const取地址操作符重载 三、再谈构造函数 1&#xff09;初始化列表 …...

CCLink转Modbus TCP网关_CCLINK参数配置

CCLink转Modbus TCP网关&#xff08;XD-ETHCL20&#xff09;&#xff0c;具有CCLINK主从站功能。主要用途是将各种MODBUS-TCP设备接入到CCLINK总线中。它可以作为从站连接到CCLINK总线上&#xff0c;也可以作为主站或从站连接到MODBUS-MTP总线上。 1、 配置网关的CCLINK参数&am…...

一文2000字从0到1使用压测神器JMeter进行压力测试!

概 述 Apache JMeter 是 Apache组织开发的基于 Java的压力测试工具。用于对软件做压力测试&#xff0c;它最初被设计用于 Web应用测试但后来扩展到其他测试领域。它可以用于测试静态和动态资源例如静态文件、Java 小服务程序、CGI 脚本、Java 对象、数据库&#xff0c; FTP 服…...

极狐GitLab CI 助力 .Net 项目研发效率和质量双提升

目录 .NET nuget 自动生成测试包&#xff08;prerelease&#xff09;版本号 .NET 版本号规范 持续集成自动打包 持续集成自动修改版本号 .NET 行级增量代码规范——拯救老项目 本地全量代码规范 行级增量代码规范 很多团队或开发者都会使用 C#、VB 等语言开发 .Net 应用…...

[协程]生成器协程调度器的实现-未完

本章内容的三个层次...

Git之分支与版本->课程目标及知识点的应用场景,分支的场景应用,标签的场景应用

1.课程目标及知识点的应用场景 Git分支和标签的命名规范 分支 dev/test/pre/pro(即master) dev:开发环境--windows (自己的电脑) test:测试环境--windows/linux (公司专门的测试电脑 pre:灰度环境(非常大的公司非常重要的项目) pro:正式环境 灰度环境与正式环境的服务器配置…...

PHP正则提取或替换img标记属性

<?php/*PHP正则提取图片img标记中的任意属性*/ $str <center><img src"/uploads/images/20100516000.jpg" height"120" width"120"><br />PHP正则提取或更改图片img标记中的任意属性</center>;//1、取整个图片代码…...

Git 命令行使用指南

Git 命令行使用指南 第一部分&#xff1a;配置 Git 1.1 设置用户信息1.2 配置换行符处理 第二部分&#xff1a;创建和配置仓库 2.1 初始化仓库2.2 克隆仓库2.3 递归克隆2.4 深度克隆 第三部分&#xff1a;基本操作 3.1 添加文件3.2 提交更改3.3 查看状态和提交历史3.4 创建和切…...

Spring 常见面试题

1、Spring概述 1.1、Spring是什么? Spring是一个轻量级Java开发框架,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题Spring最根本的使命是解决企业级应用开发的复杂性&#xff0c;即简化Java开发。这些功能的底层都依赖于它的两个核心特性&#xff0c;也就是…...

caffe搭建squeezenet网络的整套工程

之前用pytorch构建了squeezenet&#xff0c;个人觉得pytorch是最好用的&#xff0c;但是有的工程就是需要caffe结构的&#xff0c;所以本篇也用caffe构建一个squeezenet网络。 数据处理 首先要对数据进行处理&#xff0c;跟pytorch不同&#xff0c;pytorch读取数据只需要给数据…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...