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中的重要应用的更多相关文章

  1. JVM详解之:HotSpot VM中的Intrinsic methods

    目录 简介 什么是Intrinsic Methods 内置方法的特点 多样性 兼容性 java语义的扩展 Hotspot VM中的内置方法 intrinsic方法和内联方法 intrinsic方法的实 ...

  2. HotSpot VM 中的JIT分类

    在HotSpot VM中内嵌有两个JIT编译器,分别为Client Compiler和Server Compiler,但大多数情况下我们简称为C1编译器和C2编译器.开发人员可以通过如下命令显式指定J ...

  3. 转:什么是即时编译(JIT)!?OpenJDK HotSpot VM剖析

    重点 应用程序可以选择一个适当的即时编译器来进行接近机器级的性能优化. 分层编译由五层编译构成. 分层编译提供了极好的启动性能,并指导编译的下一层编译器提供高性能优化. 提供即时编译相关诊断信息的JV ...

  4. HotSpot VM运行时

    HotSpot VM运行时系统为HotSpot JIT编译器和垃圾收集器提供服务和通用API,同时还为VM提供启动.线程管理.JNI(Java本地接口)等基本功能.HotSpot VM运行时环境担当许 ...

  5. 什么是HotSpot VM & 深入理解Java虚拟机

    参考 http://book.2cto.com/201306/25434.html 另外,这篇文章也是从一个系列中得出的: <深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)> ...

  6. 关于HotSpot VM以及Java语言的动态编译 你可能想知道这些

    目录 1 HotSpot VM的历史 2 HotSpot VM 概述 2.1 编译器 2.2 解释器 2.3 解释型语言 VS 编译型语言 3 动态编译 3.1 什么是动态编译 3.2 HotSpot ...

  7. 014-通过JDB调试,通过HSDB来查看HotSpot VM的运行时数据

    一.JDB调试        在预发环境下进行debug时,时常因为工具和环境的限制,导致debug体验非常差,那么有什么方法能够简化我们进行debug的体验吗?JDB就是一种.        JDB ...

  8. Unable to open socket file: target process not responding or HotSpot VM not loaded

    Unable to open socket file: target process not responding or HotSpot VM not loaded The -F option can ...

  9. HotSpot VM GC 的种类

    collector种类 GC在 HotSpot VM 5.0里有四种: incremental (sometimes called train) low pause collector已被废弃,不在介 ...

  10. HotSpot VM

    1.4.2 Sun HotSpot VM_深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)_红黑联盟读书频道 http://book.2cto.com/201306/25434.html 提 ...

随机推荐

  1. [Qt开发]一口气搞懂串口通信

    好多小鳄鱼 一.关于串口通信: Qt的确有自己的串口通信类,就是QSerialPort,但是我们在使用过程中因为要更加定制化的使用串口通信类减小开发的难度,所以我们会提供一个串口通信类,也就是这个Se ...

  2. java匿名内部类的初解

    java原生态中的匿名内部类 1.匿名内部类的定义 使用匿名内部类的两种的方法 建立父类,重写父类的方法 实现接口的方法 2.普通类的实现 1. 普通类实现 实现普通类需要先声明对一个类的对象,再调用 ...

  3. @SafeVarargs注解的使用

    在声明具有模糊类型(比如:泛型)的可变参数的构造函数或方法时,Java编译器会报unchecked警告.鉴于这些情况,如果程序员断定声明的构造函数和方法的主体不会对其varargs参数执行潜在的不安全 ...

  4. spring-boot-maven-plugin插件详解

    一. 为什么Spring Boot项目自带这个插件 当我们在SpringBoot官方下载一个脚手架时,会发现pom.xml会自带spring-boot-maven-plugin插件 <?xml ...

  5. MD文本编辑工具推荐-matktext

    最开始是用vscode编辑markdown文档,左边写右边看效果的实时渲染模式,对于markdown编辑来说是多余的,多是文字类的内容,配以插图,复杂表格和脑图则更少.之后接触到Typora,所打即所 ...

  6. Java 中怎样将 bytes 转换为 long 类型?

    将bytes 转换为long类型: 第一种方式: String 接收 bytes 的构造器转成 String,再 Long.parseLong: 但此种情况需要注意:字节数组中的每个字节都必须是有效的 ...

  7. 一:wince 开发环境

    1:下载相关文件,vs2008 可以自行搜索安装 链接:https://pan.baidu.com/s/1b2shwCqmc1o9x-zsy8CmeA 提取码:qing

  8. Android Studio开发小项目

    "莆仙小馆"--莆田文化展示APP 文化展示程序目的在于应用科学技术助推家乡优秀传统文化的展示与交流.通过图片.视频.音频等展示方式向用户立体地展示一个文化城邦.传统文化与科学技术 ...

  9. ubuntu 安装pip3 报错

    运行命令 sudo apt install python3-pip 报错: 有几个软件包无法下载,要不运行apt-get update 或加上--fix-missing试试 输入命令: sudo ap ...

  10. spring-mvc系列:简介和基本使用

    目录 一.简介 1.什么是MVC 2.什么是SpringMVC 3.SpringMVC的特点 二.基本使用 1.开发环境 2.创建maven工程 3.配置web.xml 4.创建SpringMVC的配 ...