首页 > 编程语言 >C++ RAII在HotSpot VM中的重要应用

C++ RAII在HotSpot VM中的重要应用

时间:2023-09-21 18:44:10浏览次数:40  
标签:调用 Java RAII VM HotSpot 资源

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性能剖析与故障诊断等话题,欢迎加入。

标签:调用,Java,RAII,VM,HotSpot,资源
From: https://www.cnblogs.com/mazhimazhi/p/17673300.html

相关文章

  • 循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(6) -- 窗口控
    在我们窗口新增、编辑状态下的时候,我们往往会根据是否修改过的痕迹-也就是脏数据状态进行跟踪,如果用户发生了数据修改,我们在用户退出窗口的时候,提供用户是否丢弃修改还是继续编辑,这样在一些重要录入时的时候,可以避免用户不小心关掉窗口,导致窗口的数据要重新录入的尴尬场景。本篇随......
  • Tomcat的增加/查看jvm虚拟内存&设置JRE
    Win 操作系统 第一种方法:修改 tomcat/bin/catalina.bat 文件增加一行 setJAVA_OPTS=-Xms128M-Xmx512M-XX:PermSize=64M-XX:MaxPermSize=128M  第二种方法:在环境变量中设置变量名:JAVA_OPTS变量值:-Xms512m-Xmx512m 第三种方法:前两种方法针对的是bin目录下有catalina.bat......
  • centos 创建 lvm
    查看磁盘使用#df-hFilesystemSizeUsedAvailUse%Mountedondevtmpfs3.9G03.9G0%/devtmpfs3.9G03.9G0%/dev/shmtmpfs3.9G18M3.9G1%/runtmpfs......
  • Gavvmal
    Gavvmalspringboot官方文档说明了两种方式,一种使用插件,直接生成docker镜像,但是这需要本地安装docker环境,但是无论用windows还是mac,本地安装docker都感觉不好,太占用资源。第二种方法,安装Gavvmal,下载相应版本的压缩包,可以把这个压缩版看做一个JDK,解压后,配置JAVAHOME和path等环境......
  • vmware虚拟机中的centos设置固定ip
    1、使用桥接模式,确保虚拟机目前可联网因为我们要使用目前的配置,使得目前ip为固定ip,确保ip无冲突 2、查看目前ip配置ipaddrshow #查看ip,找到虚拟机目前联网的网络接口,我的是ens33ipaddrshowens33 #查看,确定inet172.16.200.102/20  ip和子网掩码iproute......
  • graalvm jdk 21 版本发布
    graalvm效率还是挺快的,java21版本虚拟线程以及ga可,graalvm对于21版本支持的发布,让我们也可以直接使用了从官方介绍以及解决来看,性能提升是很大的,在一些测试场景中nativeimage比C2jit还快说明目前官方已经提供了21的下载包可以体验使用参考资料https://www.graalvm.......
  • 关于“VMware ESXi OpenSLP堆溢出漏洞”的修复说明​
    关于“VMwareESXiOpenSLP堆溢出漏洞”的修复说明前段时间IT圈被一个“ESXiArgs勒索软件攻击VMwareESXi服务器”的相关新闻刷屏。互联网上的文章称,这些攻击活动似乎利用CVE-2021-21974漏洞,由OpenSLP服务中的堆溢出问题引起,未经身份验证的威胁参与者可以利用该问题进行低复......
  • vmware下安装fedora
    1、首先安装好vmware(这个网上已经有很多资料,在此不再赘述)2、下载fedora镜像(这里fedora15为例),附上几个下载地址(可以用迅雷来下载)http://download.fedoraproject.org/pub/fedora/linux/releases/15/Fedora/i386/iso/Fedora-15-i386-DVD.isox86_64:http://download......
  • 【Vue】大悟!MVVM模型
    hello,我是小索奇,精心制作的Vue教程持续更新哈,想要学习&巩固&避坑就一起学习叭~MVVM模型Vue虽然没有完全遵循MVVM模型,但Vue的设计也收到了它的启发在文档中也会使用VM(ViewModel的缩写)这个变量名表示Vue实例(Vue作者参考了MVVM模型,并非其创建的)img模型说明M:模型Model-对应data中的数......
  • How to SupressWarnings for Sonar Security Hotspots?
    HowtoSupressWarningsforSonarSecurityHotspots?Sonarlint/SonarQubeallowsyoutousecommentsfordisablinganalysisinspecificlines.Inordertodothis,youcanjustaddacommentwiththetextNOSONARinthesameline:Randomrand=newRandom()......