jvm源码解读--05 常量池 常量项的解析JVM_CONSTANT_Utf8
当index=18的时候JVM_CONSTANT_Utf8
case JVM_CONSTANT_Utf8 : { cfs->guarantee_more(2, CHECK); // utf8_length u2 utf8_length = cfs->get_u2_fast(); u1* utf8_buffer = cfs->get_u1_buffer(); assert(utf8_buffer != NULL, "null utf8 buffer"); // Got utf8 string, guarantee utf8_length+1 bytes, set stream position forward. cfs->guarantee_more(utf8_length+1, CHECK); // utf8 string, tag/access_flags cfs->skip_u1_fast(utf8_length); // Before storing the symbol, make sure it's legal if (_need_verify) { //不进入 verify_legal_utf8((unsigned char*)utf8_buffer, utf8_length, CHECK); } if (EnableInvokeDynamic && has_cp_patch_at(index)) { //不进入 Handle patch = clear_cp_patch_at(index); guarantee_property(java_lang_String::is_instance(patch()), "Illegal utf8 patch at %d in class file %s", index, CHECK); char* str = java_lang_String::as_utf8_string(patch()); // (could use java_lang_String::as_symbol instead, but might as well batch them) utf8_buffer = (u1*) str; utf8_length = (int) strlen(str); } unsigned int hash; //has值 $35 = 1818100338 Symbol* result = SymbolTable::lookup_only((char*)utf8_buffer, utf8_length, hash); //$34 = (Symbol *) 0x7f258408b478 if (result == NULL) { names[names_count] = (char*)utf8_buffer; lengths[names_count] = utf8_length; indices[names_count] = index; hashValues[names_count++] = hash; if (names_count == SymbolTable::symbol_alloc_batch_size) { SymbolTable::new_symbols(_loader_data, _cp, names_count, names, lengths, indices, hashValues, CHECK); names_count = 0; } } else { _cp->symbol_at_put(index, result); } } break;
//橘色的为Symbol,打印一下,看内容是什么
(gdb) p SymbolTable::_the_table $32 = (SymbolTable *) 0x7f258002eab8 (gdb) p *SymbolTable::_the_table $33 = (SymbolTable) {<Hashtable<Symbol*, 2304u>> = {<BasicHashtable<2304u>> = {<CHeapObj<2304u>> = {<AllocatedObj> = {_vptr.AllocatedObj = 0x7f2586b80af0 <vtable for SymbolTable+16>}, <No data fields>}, _table_size = 20011, _buckets = 0x7f25876b3028, _free_list = 0x0, _first_free_entry = 0x7f25800519b8 "\361\..." <incomplete sequence \361>..., _end_block = 0x7f2580054598 "\253\253\253\253\253\253\253\253\253\253\253\253\253\253\253\253\205", _entry_size = 32, _number_of_entries = 672, _lookup_count = 0, _lookup_length = 0}, static _seed = <optimized out>}, static _the_table = 0x7f258002eab8, static _needs_rehashing = false, static symbols_removed = 0, static symbols_counted = 0, static _arena = 0x7f258002eb28}
//里面是一个Hashtable,哈希表,里面有桶的
接着进入紫色的
void symbol_at_put(int which, Symbol* s) { assert(s->refcount() != 0, "should have nonzero refcount"); tag_at_put(which, JVM_CONSTANT_Utf8); *symbol_at_addr(which) = s; } Symbol** symbol_at_addr(int which) const { assert(is_within_bounds(which), "index out of bounds"); return (Symbol**) &base()[which]; }
打印一下这个Symbol
(gdb) p sizeof(Symbol) $36 = 12 $38 = {<SymbolBase> = {<MetaspaceObj> = {<No data fields>}, _length = 6, _refcount = -1, _identity_hash = 1186001213}, _body = {60 '<'}, static _total_count = 0}
以上就完成了 JVM_CONSTANT_Utf8 的解析
查看经常用的函数p s->as_C_string()
char* Symbol::as_C_string() const { int len = utf8_length(); char* str = NEW_RESOURCE_ARRAY(char, len + 1); return as_C_string(str, len + 1); } int utf8_length() const { return _length; }
//
其中_length定义在SymbolBase的类中
class SymbolBase : public MetaspaceObj { public: ATOMIC_SHORT_PAIR( volatile short _refcount, // needs atomic operation unsigned short _length // number of UTF8 characters in the symbol (does not need atomic op) ); int _identity_hash; };
接着
char* Symbol::as_C_string(char* buf, int size) const { if (size > 0) { int len = MIN2(size - 1, utf8_length()); for (int i = 0; i < len; i++) { buf[i] = byte_at(i); } buf[len] = '\0'; } return buf; } int byte_at(int index) const { assert(index >=0 && index < _length, "symbol index overflow"); return base()[index]; } const jbyte* base() const { return &_body[0]; } jbyte _body[1];
说明Symbol这个类,字符在_body字段中,长度在父类中
去符号表中查找,符号表实例,所以常量池中存储的是Symbol* 指针; (gdb) p SymbolTable::_the_table $32 = (SymbolTable *) 0x7f258002eab8 (gdb) p *SymbolTable::_the_table