04、jvm源码解读 - 常量池 常量项的解析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