C++的模板类在HotSpot VM中的应用

模板是c++的一种特性,允许函数或者类通过泛型(generic types)的形式表现或者运行。模板可以使得函数或类在对应不同的类型(types)的时候正常工作,而无需为每一种类型分别写一份代码。

在HotSpot VM中定义了一些模板类,有了这些模板类,我们就可以和Java一样进行泛型编程。HotSpot VM中定义了Dictionary和SymbolTable等用来存储类和字符串等内容的Hash表,这些容器类都使用到了模板类。

看一下具体的定义,如下:

复制代码
源代码位置:/media/mazhi/sourcecode/workspace/projectjava9/learnhotspot/src/utilities/hashtable.hpp

template <MEMFLAGS F> class BasicHashtable : public CHeapObj<F> {
  ...
private:
  int               _table_size;
  HashtableBucket<F>*     _buckets;

  BasicHashtableEntry<F>* bucket(int i);
  ...
 }

template <MEMFLAGS F> class BasicHashtableEntry : public CHeapObj<F> {
private:
  unsigned int         _hash;          
  BasicHashtableEntry<F>* _next;
  ...
}

定义了一个名称为BasicHashtable的类模板,类模板以template关键字开始,后面跟着模板参数列表。这里在模板中定义了一个非类型参数,一个非类型参数表示一个值而不是一个类型。它的定义如下:

复制代码
typedef unsigned short MEMFLAGS;

其定义的非类型参数F也应用到了类模板HashtableBucket<F>中了,同样也可以应用到函数的参数和返回类型中。

通过BasicHashtable这个类模板的定义可以看出,通过此类模板生成的表或字典是通过列表来解决Hash冲突的。

下面接着看另外一个类模板,如下:

复制代码
源代码位置:/media/mazhi/sourcecode/workspace/projectjava9/learnhotspot/src/utilities/hashtable.hpp

template <class T, MEMFLAGS F> class Hashtable : public BasicHashtable<F> {
 protected:
   ...
   HashtableEntry<T, F>* bucket(int i) {
     return (HashtableEntry<T, F>*)BasicHashtable<F>::bucket(i);
   }
}

template <class T, MEMFLAGS F> class HashtableEntry : public BasicHashtableEntry<F> {
private:
  T  _literal;   // ref to item in table.
  ...
}

这次的类模板继承了BasicHashtable<F>,不过这个类模板中通过class关键字定义了一个模板类型参数T,这其实就是我们要真正往Hash表中存储的元素的类型。

SymbolTable和StringTable都使用了如上的类模板,如SymbolTable类的定义如下:

复制代码
class SymbolTable : public Hashtable<Symbol*, mtSymbol> {
...
}

为类型模板参数指定了具体的类型。也就是这个Hash表中存储的元素类型为Symbol*,而在为这些元素分配内存时,将这些内存统计到mtSymbol上,这样NMT就能追踪这一部分使用内存的详细信息了。

下面看一下存储类的字典的定义,如下:

复制代码
template <class T, MEMFLAGS F> class TwoOopHashtable : public Hashtable<T, F> {
...
}

class Dictionary : public TwoOopHashtable<Klass*, mtClass> {
...
}

存储Java类的字典Dictionary继承了TwoOopHashtable<Klass*,mtClass>,这是因为在Java世界中,只有类全名和类加载器才能唯一表示一个类,所以继承这个类也起到了一个见名知义的效果。

另外还有一点需要说明,就是C++对模板的分离式编译很弱。对于 BasicHashtable 中定义的bucket()函数来说,其实现是在hashtable.cpp文件中,其实严格来说,这不是函数的定义,而是生成定义的一种方案,只有在实例化时,才能生成函数定义,所以我们能在hashtable.cpp文件中看到如下类似的语句:

复制代码
template class BasicHashtable<mtSymbol>;

在.cpp文件的末尾加上如上代码来显式实例化,这样我们将hashtable.cpp作为源文件加入编译时,整个程序就有了模板的显式实例化,即函数定义。否则可能报"undefined reference to"相关的错误。

本人最近准备出一个手写Hotspot VM的课程,超级硬核,从0开始写HotSpot VM,将HotSpot VM所有核心的实现全部走一遍,如感兴趣,加我速速入群。

群里可讨论虚拟机和Java性能剖析与故障诊断等话题,欢迎加入。

相关推荐
彧翎Pro4 小时前
基于 RO1 noetic 配置 robosense Helios 32(速腾) & xsense mti 300
前端·jvm
minji...8 小时前
Linux 线程同步与互斥(二) 线程同步,条件变量,pthread_cond_init/wait/signal/broadcast
linux·运维·开发语言·jvm·数据结构·c++
woai33649 小时前
JVM学习-基础篇-常见引用
jvm·学习
それども10 小时前
理解JVM参数 Xss 线程的栈大小
jvm
玛卡巴卡ldf10 小时前
【Springboot6】内存泄漏OOM、VisualVM、Arthas、Prometheus Grafana监控、垃圾回收
java·jvm·springboot
一个有温度的技术博主10 小时前
深入多级缓存:JVM进程缓存实战与数据库表拆分策略
jvm·数据库·缓存
码云数智-园园11 小时前
C# 内存模型的基石:值类型与引用类型的深度博弈
java·开发语言·jvm
Engineer邓祥浩12 小时前
JVM学习笔记(7) 第三部分 虚拟机执行子系统 第6章 类文件结构
jvm·笔记·学习
大黄说说12 小时前
深入.NET内存模型:垃圾回收(GC)机制与性能优化指南
java·jvm·算法
搜佛说2 天前
比SQLite更快,比InfluxDB更轻:sfsDb的降维打击
jvm·数据库·物联网·架构·sqlite·边缘计算·iot