当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

jvm源码解读--05 常量池 常量项的解析JVM_CONSTANT_Utf8的更多相关文章

  1. JVM 源码解读之 CMS 何时会进行 Full GC

    t点击上方"涤生的博客",关注我 转载请注明原创出处,谢谢!如果读完觉得有收获的话,欢迎点赞加关注. 前言 本文内容是基于 JDK 8 在文章 JVM 源码解读之 CMS GC 触 ...

  2. jvm源码解读--17 Java的wait()、notify()学习

    write and debug by 张艳涛 wait()和notify()的通常用法 A线程取得锁,执行wait(),释放锁; B线程取得锁,完成业务后执行notify(),再释放锁; B线程释放锁 ...

  3. jvm源码解读--04 常量池 常量项的解析CONSTANT_Class_info

    接上篇的继续 ConstantPool* constant_pool = ConstantPool::allocate(_loader_data, length, CHECK_(nullHandle) ...

  4. jvm源码解读--03 常量池的解析ConstantPool

    先看bt栈 (gdb) bt #0 ConstantPool::allocate (loader_data=0x7fe21802e868, length=87, __the_thread__=0x7f ...

  5. jvm源码解读--08 创建oop对象,将static静态变量放置在oop的96 offset处

    之前分析的已经加载的.Class文件中都没有Static 静态变量,所以也就没这部分的解析,自己也是不懂hotspot 将静态变量放哪里去了,追踪源码之后,看清楚了整个套路,总体上来说,可以举例来说对 ...

  6. jvm源码解读--12 invokspecial指令的解读

    先看代码 package com.zyt.jvmbook; public class Girl extends Person{ public Girl() { int a; } @Override p ...

  7. jvm源码解读--09 创建oop对象,将static静态变量放置在oop的96 offset处 第二篇

    先打断点systemDictionary.cpp 1915行 Universe::fixup_mirrors(CHECK); 进入 void Universe::fixup_mirrors(TRAPS ...

  8. C# ArrayPool 源码解读之 byte[] 池化

    一:背景 1. 讲故事最近在分析一个 dump 的过程中发现其在 gen2 和 LOH 上有不少size较大的free,仔细看了下,这些free生前大多都是模板引擎生成的html片段的byte[]数组 ...

  9. jvm源码解读--16 cas 用法解析

    CAS的意思是campare and sweep比较交换 这个如果不用代码会比较抽象,那么在源码中进行解释 void ATTR ObjectMonitor::enter(TRAPS) { // The ...

随机推荐

  1. SSM框架集成各配置文件

    SSM框架集成各配置文件 Spring Spring MVC Mybatis 的整合SpringMVC相当于Spring的一个组件 本来就是一个家族的不存在整合的问题,所以主要就是Spring于Myb ...

  2. 数据库创建好之后如何创建scott用户

    SQL> conn / as sysdba Connected. SQL> @%oracle_home%\rdbms\admin\utlsampl.sql 建立完成以后会自动退出sqlpl ...

  3. YOLO V4的模型训练

    1.YOLO V4模型训练的基本思路 所有机器学习涉及模型训练,一般都有训练集.验证集.测试集,因此需要准备数据集.有了数据集,再调用训练的算法,获取训练的结果.v3.v4模型训练方法相同. 2.YO ...

  4. 环境安装——JDK安装

    @ 目录 开发环境-JDK安装 1. 下载地址 2. 安装JDK 3. 配置系统环境 开发环境-JDK安装 无论在我们开始学习Java或者入职第一天安装环境,这个你都是必备滴!下面是下载和安装JDK的 ...

  5. <mvc:default-servlet-handler/>导致controller失效,报404错误

    最近在做ssm框架整合的一个小项目时,页面跳转一直有404错误,也没有报错提示.然后一步一步去找,终于发现是<mvc:default-servlet-handler/>的原因.如下图所示, ...

  6. 6-x2 echo命令:将指定字符串输出到 STDOUT

    echo 用法 常用转义符 echo 用法     echo 用来在终端输出字符串,并在最后默认加上换行符. echo 加上-n参数可以使数据字符串后不再换行 echo 加上-e参数可以解析转义字符 ...

  7. php 错误处理及实现

    1.php的错误,警告,异常处理如何实现,那些函数用于处理对应的错误 php 异常提示分为三类 error/warning/notice   错误补充:   Fatal Error:致命错误(脚本终止 ...

  8. C++实现KDTree

    简介   k-d树(k-dimensional),是一种分割k维数据空间的数据结构(对数据点在k维空间中划分的一种数据结构),主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 举例    ...

  9. Leetcode No.167 Two Sum II - Input array is sorted(c++实现)

    1. 题目 1.1 英文题目 Given an array of integers numbers that is already sorted in non-decreasing order, fi ...

  10. python多线程实现方式,最基础的实现方式模块是什么

    https://blog.csdn.net/daiyu__zz/article/details/81912018 python3.x中通过threading模块创建新的线程有两种方法:一种是通过thr ...