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

相关推荐
阿龟在奔跑11 小时前
引用类型的局部变量线程安全问题分析——以多线程对方法局部变量List类型对象实例的add、remove操作为例
java·jvm·安全·list
王佑辉12 小时前
【jvm】方法区常用参数有哪些
jvm
王佑辉12 小时前
【jvm】HotSpot中方法区的演进
jvm
Domain-zhuo12 小时前
什么是JavaScript原型链?
开发语言·前端·javascript·jvm·ecmascript·原型模式
Theodore_10221 天前
7 设计模式原则之合成复用原则
java·开发语言·jvm·设计模式·java-ee·合成复用原则
我是苏苏1 天前
Web开发:ORM框架之使用Freesql的DbFrist封装常见功能
java·前端·jvm
出发行进2 天前
Flink错误:一historyserver无法启动,二存在的文件会报错没有那个文件或目录
大数据·linux·hadoop·flink·虚拟机
天草二十六_简村人2 天前
Java语言编程,通过阿里云mongo数据库监控实现数据库的连接池优化
java·jvm·数据库·mongodb·阿里云·微服务·云计算
老码沉思录2 天前
Android开发实战班 - 数据持久化 - Room 数据库应用
android·jvm·数据库
起名字真南2 天前
【C++】深入理解 C++ 中的继承进阶:多继承、菱形继承及其解决方案
java·jvm·c++·chatgpt·aigc