JVM的运行时常量池ConstantPoolCache实现分析

170 阅读2分钟

基于前面介绍的JVM经过Rewriter字节码重写,在ConstantPool中创建了常量池缓存ConstantPoolCache对象, ConstantPoolCache不是常量池缓存,它其实是实例和静态的字段和方法调用的解析表,JVM的ConstantPoolCache类 其中主要字段如下
_length : 常量池长度
_constant_pool: 对应的常量池
_resolved_references : 已经解析的引用
_reference_map : 从常量池已经解析的对象, 并从已经解析的对象索映射到原始常量池的索引
_resolved_indy_entries: 包含调用动态字节码的解析信息 \

其中每一项都是保存ConstantPoolCache对象地址结尾的ConstantPoolCacheEntry数组

class ConstantPoolCache: public MetaspaceObj {
 private:

  int             _length;
  ConstantPool*   _constant_pool;     

  OopHandle            _resolved_references;
  Array<u2>*           _reference_map;

  Array<ResolvedIndyEntry>* _resolved_indy_entries;
  
ConstantPoolCacheEntry* base() const {
return (ConstantPoolCacheEntry*)((address)this + in_bytes(base_offset())); 
}

ConstantPoolCacheEntry是描述常量池项的信息, 其主要字段如下: _indices : 常量池的索引
_f1 : 表示method或klass元数据
_f2: vtable索引或final方法指针
_flags : 标志位 \

_indices 的存储分布如下:\

|bit number |31 0|
|bit length |-8--|-8--|---16----|

_indices [ b2 | b1 | index ] index = 常量池索引
_f1 [ entry specific ] method or klass 元数据指针
_f2 [ entry specific ] vtable索引, or final方法指针
_flags [tos|0|F=1|0|0|0|f|v|0 |0000|field_index] (for field entries)
bit length [ 4 |1| 1 |1|1|1|1|1|1 |1 |-3-|----16-----]
_flags [tos|0|F=0|S|A|I|f|0|vf|indy_rf|000|00000|psize] (for method entries)
bit length [ 4 |1| 1 |1|1|1|1|1|1 |-4--|--8--|--8--]

_flags 的 31, 30, 29, 28四个bit位存储TosState(栈顶状态)映射值如下 btos: 0 ztos: 1 ctos: 2 stos: 3 itos: 4 ltos: 5 ftos: 6 dtos: 7 atos: 8 vtos: 9

field 的ConstantPoolCacheEntry内存布局如下: _indices 获取field存在 b1位置,存储field存在 b2位置,原始常量池索引
_f1 java.lang.Class的实例
_f2 field的偏移地址
_flags FieldInfo类型存储的field索引

method 的ConstantPoolCacheEntry内存布局如下:
_indices 调用_f1存在b1位置, 调用_f2存在b2位置,低16位存原始常量池索引
_f1 Method指针
_f2 vtable/itable索引 或者 虚final的方法
_flags 虚final位 psize位置存参数大小

ConstantPoolCacheEntry存储在ConstantPoolCache对象的尾部的指针数组

class ConstantPoolCacheEntry {
 private:
  volatile intx    _indices;   virtual final bit
  Metadata* volatile   _f1;     
  volatile intx        _f2;    
  volatile intx     _flags; 
}

ConstantPoolCache和ConstantPoolCacheEntry存储如下图

image.png

总结
本文主要对ConstantPoolCache对象,以及内部存储的ConstantPoolCacheEntry内部布局有一个初步的认识。