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

  

相关推荐
2601_9622992411 小时前
Azure python操作系统列表
python·操作系统·azure·虚拟机·存储配置文件
袋鼠云数栈18 小时前
整库迁移与分库分表同步:批量数据搬迁的配置简化思路
jvm·数据库·oracle
Mr. zhihao1 天前
JVM 偏向锁 4 秒延迟:从源码动机到 JEP-374 废弃全链路
jvm·并发·偏向锁
孙克旭_1 天前
JVM 入门详解:JVM、JRE、JDK 区别,JVM 基础结构梳理
java·开发语言·jvm
随遇而安zx1 天前
【地基篇】---JVM 内存结构知识点(Java 8 运行时数据区深度解析)
java·开发语言·jvm
恒拓高科WorkPlus1 天前
企业如何搭建安全内部通讯平台|企业内部通讯平台怎么选才更安全?
jvm·数据库·安全
随遇而安zx1 天前
【地基篇】---JVM 类加载 源码解析(基于 Java 8)
java·jvm·python
ly76892 天前
JVM 类加载机制:打破双亲委派模型的实践与陷阱
jvm·热部署·spi·类加载器·双亲委派
随遇而安zx2 天前
【地基篇】---Java 8 JVM 知识大纲
java·开发语言·jvm
liangbo72 天前
01-JVM 内存模型全景
java·jvm