C++ RAII在HotSpot VM中的重要应用
RAII(Resource Acquisition Is Initialization),也称为“资源获取就是初始化”,是C++语言的一种管理资源、避免泄漏的惯用法。C++标准保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用。简单的说,RAII的做法是使用一个对象,在其构造时获取资源,在对象生命期控制范围之下对资源的访问始终保持有效,最后在对象析构的时候释放资源。
在HotSpot VM中,RAII对内存资源的管理和释放、明确定义范围锁及记录重要信息等方面起到了非常重要的作用。下面详细介绍一下。
1、定义范围锁
在HotSpot VM中,整个系统正确的运转需要非常多的锁,这些锁很多都是通过RAII技术来管理的。
举个例子,如下:
class MutexLocker {
private:pthread_mutex_t *_mtx;
public:MutexLocker(pthread_mutex_t *mtx) {if (mtx) {_mtx = mtx;pthread_mutex_lock(_mtx);}}~MutexLocker() {if (_mtx)pthread_mutex_unlock(_mtx);}
};
在类的构造和析构函数中对互斥量进行加载和释放锁。也就是说,当对象创建的时候会自动调用构造函数,当对象超出作用域的时候会自动调用析构函数。
现在我们通过如上的类将一段代码保护起来,防止产生并发问题:
// 初始化互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;void init(){MutexLocker locker(&mutex);// 整个方法都会在同步锁的保护下执行
}
我们还可以通过匿名块来进一步细化锁控制的范围。当进入作用域范围时,C++会自动调用MutexLocker的构造函数,当出了作用域范围时,会调用MutexLocker析构函数。这样通过类来管理锁资源,将资源和对象的生命周期绑定。在Java中有个类似的、饱受诟病的一种释放资源的办法,重写finalize()方法,由于开发人员无法对Java对象的生命周期进行精确控制,而是托管给了Java虚拟机GC,所以对象什么时候回收是一个未知数,为应用程序埋下了一个定时炸弹。不过另外一个类似的语法try-with-resources提倡使用。
在HotSpot VM中,在runtime/mutex.hpp文件中定义了互斥量Mutex,这个互斥量继承自Monitor,HotSpot VM内部的并发非常依赖Monitor。在runtime/mutexLocker.hpp文件中定义了MutexLocker、MutexLockerEx等类来控制锁范围。
2、管理内存资源
管理内存资源的一些类有HandleMark、ResourceMark等,HandleMark用来管理句柄,ResourceMark用来管理临时使用的内存。
HandleMark我在之前已经介绍的非常详细了,可参考如下文章:
第2.7篇-操作句柄Handle
第2.8篇-句柄Handle的释放
ResourceMark的实现也非常类似。
由于Java类常量池中的字符串、还有一些公共字符串在HotSpot VM中都用Symbol实例来表示,如果想要看某个Klass实例表示的具体的类名称,我有时候会这样做:
{ResourceMark rm;Symbol *sym = _klass->name();const char *klassName = (sym->as_C_string());// ...
}
调用的as_C_string()函数实现如下:
char* Symbol::as_C_string() const {int len = utf8_length();char* str = (char*) resource_allocate_bytes( (len + 1) * sizeof(char) );return as_C_string(str, len + 1);
}extern char* resource_allocate_bytes(size_t size, AllocFailType alloc_failmode) {ResourceArea* ra = Thread::current()->resource_area();return ra->allocate_bytes(size, alloc_failmode);
}
可以看到从ResourceArea中申请了内存,那就必须要记录,完成调用之后恢复调用之前的样子,这样才不会让内存处在不一致的状态,从而导致崩溃,所以必须要使用ResourceMark。
3、保存重要信息
阅读HotSpot VM源代码的人一定会对JavaCalls::call_helper()函数中的如下这段代码不陌生:

从HotSpot VM内部调用Java方法时,通常会调用到call_helper()函数,所以这也是HotSpot VM调用Java主类main()方法的关键入口,在这个函数中我们能够看到HandleMark的使用,另外还有一个JavaCallWrapper,这个类主要有2个作用:
(1)管理内存资源,在 第42篇-JNI引用的管理(1) 已经详细介绍过,这里不再介绍。
(2)记录Java调用栈的重要信息,退栈等操作非常依赖这些信息。
变量名叫link非常贴切,它的起用就是将Java栈连接起来,其大概的实现过程如下图所示。

后面我们在介绍具体的知识点时再详细介绍这些内容。
RAII技术被认为是C++中管理资源的最佳方法,进一步引申,使用RAII技术也可以实现安全、简洁的状态管理,编写出优雅的异常安全的代码。它利用栈对象在离开作用域后自动析构的语言特点,将受限资源的生命周期绑定到该对象上,当对象析构时以达到自动释放资源的目的。
简单而言RAII就是指资源在我们拿到时就已经初始化,一旦不在需要该资源就可以自动释放该资源。
本人最近准备出一个手写Hotspot VM的课程,超级硬核,从0开始写HotSpot VM,将HotSpot VM所有核心的实现全部走一遍,如感兴趣,速速入群。
群里可讨论虚拟机和Java性能剖析与故障诊断等话题,欢迎加入。

相关文章:
C++ RAII在HotSpot VM中的重要应用
RAII(Resource Acquisition Is Initialization),也称为“资源获取就是初始化”,是C语言的一种管理资源、避免泄漏的惯用法。C标准保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用。简单…...
python随手小练
题目: 使用python做一个简单的英雄联盟商城登录界面 具体操作: print("英雄联盟商城登录界面") print("~ * "*15 "~") #找其规律 a "1、用户登录" b "2、新用户注册" c "3、退出系统&quo…...
MySQL——函数和流程控制
2023.9.21 函数 含义:一组预先编译好的SQL语句的集合,理解成批处理语句。 提高代码的重用性简化操作减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率 与存储过程的区别: 存储过程:可以有0个返回&am…...
【Vue3 源码讲解】nextTick
nextTick 是 Vue 3 中用于异步执行回调函数的函数,它会将回调函数延迟到下一个微任务队列中执行。其中,Vue 更新 DOM 是异步的。下面是对 nextTick 函数的详细解释: export function nextTick<T void, R void>(this: T,fn?: (this:…...
什么是ATR,在聚宽量化平台如何计算ATR
海龟们使用两种资金管理方法。首先,我们把头寸分成一个个小块。这样,即使一笔交易赔了钱,我们损失的也只是一个头寸的一部分。里奇和比尔把这些小块称作头寸单位。其次,我们使用里奇和比尔发明的一种创新性的头寸规模决定方法。这…...
Python 爬虫实战之爬淘宝商品并做数据分析
前言 是这样的,之前接了一个金主的单子,他想在淘宝开个小鱼零食的网店,想对目前这个市场上的商品做一些分析,本来手动去做统计和分析也是可以的,这些信息都是对外展示的,只是手动比较麻烦,所以…...
Python爬虫-requests.exceptions.SSLError: HTTPSConnectionPool疑难杂症解决(1)
前言 本文是该专栏的第7篇,后面会持续分享python爬虫案例干货,记得关注。 在爬虫项目开发中,偶尔可能会遇到SSL验证问题“requests.exceptions.SSLError: HTTPSConnectionPool(host=www.xxxxxx.com, port=443): Max retries exceeded with url ...”。亦或是验证之后的提示…...
12:STM32---RTC实时时钟
目录 一:时间相关 1:Unix时间戳 2: UTC/GMT 3:时间戳转化 二:BKP 1:简历 2:基本结构 三: RTC 1:简历 2: 框图 3:RTC基本结构 4:RTC操作注意 四:案例 A:读写备份寄存器 1:连接图 2: 步骤 3: 代码 B:实时时钟 1:连接图 2:函数介绍 3:代码 一:时间相关 1:Un…...
【动态规划刷题 16】最长等差数列 (有难度) 等差数列划分 II - 子序列
1027. 最长等差数列 https://leetcode.cn/problems/longest-arithmetic-subsequence/ 给你一个整数数组 nums,返回 nums 中最长等差子序列的长度。 回想一下,nums 的子序列是一个列表 nums[i1], nums[i2], …, nums[ik] ,且 0 < i1 <…...
【postgresql】替换 mysql 中的ifnull()
数据库由mysql 迁移到postgresql,程序在执行查询时候报错。 HINT: No function matches the given name and argument types. You might need to add explicit type casts. CONTEXT: referenced column: ifnull 具体SQL: SELECT ifnull(phone,) FROM c_user p…...
单例模式(懒汉式,饿汉式,变体)
单例模式,用于确保一个类只有一个实例,并提供一个全局访问点以访问该实例。 饿汉式(Eager Initialization) 程序启动时就创建实例 #include <iostream> class SingletonEager { private:static SingletonEager* instanc…...
Java Lambda表达式:简洁且强大的函数式编程工具
Lambda表达式是Java 8及以后版本中引入的一种函数式编程特性。它是一种匿名函数,允许开发人员以简洁和易读的方式编写代码,并且可以作为参数传递给方法或存储在变量中。Lambda表达式的基本语法如下:(parameters) -> expression,…...
开源框架中的责任链模式实践
作者:vivo 互联网服务器团队-Wang Zhi 责任链模式作为常用的设计模式而被大家熟知和使用。本文介绍责任链的常见实现方式,并结合开源框架如Dubbo、Sentinel等进行延伸探讨。 一、责任链介绍 在GoF 的《设计模式》一书中对责任链模定义的:将…...
智能配电系统:保障电力运行安全、可控与高效
智能配电系统是一种先进的电力分配技术,它通过智能化、数字化和网络化等方式,有效地保障了电力运行的安全、可控和高效。 力安科技智能配电系统是在配电室(含高压柜、变压器、低压柜)、箱式变电站、配电箱及动力柜(…...
MySQL学习系列(11)-每天学习10个知识
目录 1. 数据库设计的关键因素2. 使用存储过程和函数来提高性能和可重用性3. MySQL性能优化4. 使用视图简化查询和提供数据安全性5. 数据库备份和恢复策略的重要性和实践经验6. 在分布式系统中保证数据一致性和可用性7. 理解MySQL的复制和其在实际应用中的作用8. 使用游标进行分…...
如何通过Gunicorn和Niginx部署Django
本文主要介绍如何配置Niginx加载Django的静态资源文件,也就是Static 1、首先需要将Django项目中的Settings.py 文件中的两个参数做以下设置: STATIC_URL /static/ STATIC_ROOT os.path.join(BASE_DIR, static) 然后在宝塔面板中执行python manage.…...
C语言 cortex-A7核UART总线实验
一、C 1)uart4.h #ifndef __UART4_H__ #define __UART4_H__ #include "stm32mp1xx_rcc.h" #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_uart.h&quo…...
asp.net C#免费反编译工具ILSpy
在维护一个没有源码的C#项目,只能反编译了。 项目主页 https://github.com/icsharpcode/ILSpy 使用方法 中文界面使用简单,把你要反编译的dll拖过去就可以了。好使!!!...
演讲实录:DataFun 垂直开发者社区基于指标平台自主洞察北极星指标
在7月14日举办的 Kyligence 用户大会的数智新应用论坛上,DataFun COO 杜颖女士为大家带来了《垂直开发者社区基于指标平台自主洞察北极星指标》的主题演讲。接下来,我们一起看看 DataFun 如何在没有专门的 IT 团队的情况下,实现对北极星指标的…...
ffmpeg编译 Error: operand type mismatch for `shr‘
错误如下: D:\msys2\tmp\ccUxvBjQ.s: Assembler messages: D:\msys2\tmp\ccUxvBjQ.s:345: Error: operand type mismatch for shr D:\msys2\tmp\ccUxvBjQ.s:410: Error: operand type mismatch for shr D:\msys2\tmp\ccUxvBjQ.s:470: Error: operand type mismatch…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...
