在创建constantPoolOop中会为_tags域申请内存空间
constantPoolOop constantPoolKlass::allocate(int length, bool is_conc_safe, TRAPS){
//...
typeArrayOop t_oop = oopFactory::new_permanent_byteArray(length, CHECK_NULL);
typeArrayHandle tags(THREAD, t_oop);
for(int index = 0; index < length; index++){
tags()->byte_at_put(index, JVM_CONSTANT_Invalid);
}
pool->set_tags(tags());
//...
}
先看看代码
void ClassFileParser::parse_constant_pool_entries(int length, TRAPS) {
ClassFileStream* cfs0 = stream();
ClassFileStream cfs1 = *cfs0;
ClassFileStream* cfs = &cfs1;
Handle class_loader(THREAD, _loader_data->class_loader());
// Used for batching symbol allocations.
const char* names[SymbolTable::symbol_alloc_batch_size];
int lengths[SymbolTable::symbol_alloc_batch_size];
int indices[SymbolTable::symbol_alloc_batch_size];
unsigned int hashValues[SymbolTable::symbol_alloc_batch_size];
int names_count = 0;
for (int index = 1; index < length; index++) {
// Each of the following case guarantees one more byte in the stream
// for the following tag or the access_flags following constant pool,
// so we don't need bounds-check for reading tag.
u1 tag = cfs->get_u1_fast();
switch (tag) {
case JVM_CONSTANT_Class :
{
//下面的guarantee_more总是多一个字节
cfs->guarantee_more(3, CHECK); // name_index, tag/access_flags
u2 name_index = cfs->get_u2_fast();
_cp->klass_index_at_put(index, name_index);
}
break;
case JVM_CONSTANT_Fieldref :
{
cfs->guarantee_more(5, CHECK); // class_index, name_and_type_index, tag/access_flags
u2 class_index = cfs->get_u2_fast();
u2 name_and_type_index = cfs->get_u2_fast();
_cp->field_at_put(index, class_index, name_and_type_index);
}
break;
//...
default:
classfile_parse_error(
"Unknown constant tag %u in class file %s", tag, CHECK);
break;
}
}
//...
cfs0->set_current(cfs1.current());
}
主要通过一个for循环处理所有的常量池元素.先 u1 tag = cfs->get_u1_fast();读取描述元素类型,之后通过switch语句处理
以case JVM_CONSTANT_Class为例,首先u2 name_index 获取类的名称索引,cp->klass_index_at_put(index, name_index)保存至constantPoolOop的tag数组和数据区
以下图为例
一号位置的值为索引2, tag中的7为JVM_CONSTANT_Class
对方法元素有两个索引的采用拼接,将第一个索引左移两字节
对字符串则是保留指向符号区的指针
常量池解析完成