jvm源码解读--03 常量池的解析ConstantPool
先看bt栈
(gdb) bt
#0 ConstantPool::allocate (loader_data=0x7fe21802e868, length=87, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/oops/constantPool.cpp:47
#1 0x00007fe2206d0bbc in ClassFileParser::parse_constant_pool (this=0x7fe22229a010, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classFileParser.cpp:331
#2 0x00007fe2206dce84 in ClassFileParser::parseClassFile (this=0x7fe22229a010, name=0x7fe21d4ad0e8, loader_data=0x7fe21802e868, protection_domain=..., host_klass=..., cp_patches=0x0, parsed_name=..., verify=false, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classFileParser.cpp:3774
#3 0x00007fe2206eb9b5 in ClassFileParser::parseClassFile (this=0x7fe22229a010, name=0x7fe21d4ad0e8, loader_data=0x7fe21802e868, protection_domain=..., parsed_name=..., verify=false, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classFileParser.hpp:468
#4 0x00007fe2206e97cb in ClassLoader::load_classfile (h_name=0x7fe21d4ad0e8, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classLoader.cpp:931
#5 0x00007fe220d29903 in SystemDictionary::load_instance_class (class_name=0x7fe21d4ad0e8, class_loader=..., __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1304
#6 0x00007fe220d27ced in SystemDictionary::resolve_instance_class_or_null (name=0x7fe21d4ad0e8, class_loader=..., protection_domain=..., __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:779
#7 0x00007fe220d266be in SystemDictionary::resolve_or_null (class_name=0x7fe21d4ad0e8, class_loader=..., protection_domain=..., __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:232
#8 0x00007fe220d2612f in SystemDictionary::resolve_or_fail (class_name=0x7fe21d4ad0e8, class_loader=..., protection_domain=..., throw_error=true, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:171
#9 0x00007fe220d26451 in SystemDictionary::resolve_or_fail (class_name=0x7fe21d4ad0e8, throw_error=true, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:212
#10 0x00007fe220d2b27b in SystemDictionary::initialize_wk_klass (id=SystemDictionary::Object_klass_knum, init_opt=0, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1866
#11 0x00007fe220d2b39e in SystemDictionary::initialize_wk_klasses_until (limit_id=SystemDictionary::Cloneable_klass_knum, start_id=@0x7fe22229a9ec: SystemDictionary::Object_klass_knum, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1882
#12 0x00007fe220d2eb86 in SystemDictionary::initialize_wk_klasses_through (end_id=SystemDictionary::Class_klass_knum, start_id=@0x7fe22229a9ec: SystemDictionary::Object_klass_knum, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.hpp:408
#13 0x00007fe220d2b4d0 in SystemDictionary::initialize_preloaded_classes (__the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1901
#14 0x00007fe220d2b19d in SystemDictionary::initialize (__the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1843
#15 0x00007fe220d7c1d1 in Universe::genesis (__the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/memory/universe.cpp:288
#16 0x00007fe220d7e439 in universe2_init () at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/memory/universe.cpp:991
#17 0x00007fe220917a5c in init_globals () at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/runtime/init.cpp:114
#18 0x00007fe220d5f756 in Threads::create_vm (args=0x7fe22229ae40, canTryAgain=0x7fe22229adff) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/runtime/thread.cpp:3424
#19 0x00007fe2209ca232 in JNI_CreateJavaVM (vm=0x7fe22229ae88, penv=0x7fe22229ae80, args=0x7fe22229ae40) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/prims/jni.cpp:5166
#20 0x00007fe221c67780 in InitializeJVM (pvm=0x7fe22229ae88, penv=0x7fe22229ae80, ifn=0x7fe22229ae90) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/jdk/src/share/bin/java.c:1145
#21 0x00007fe221c656f9 in JavaMain (_args=0x7ffe14eb62f0) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/jdk/src/share/bin/java.c:371
#22 0x00007fe221e81ea5 in start_thread () from /lib64/libpthread.so.0
#23 0x00007fe22178a9fd in clone () from /lib64/libc.so.6
进入这个函数
ConstantPool*MetaWord(ClassLoaderData* loader_data, int length, TRAPS) {
// Tags are RW but comment below applies to tags also.
Array<u1>* tags = MetadataFactory::new_writeable_array<u1>(loader_data, length, 0, CHECK_NULL); int size = ConstantPool::size(length); //length=87 // CDS considerations:
// Allocate read-write but may be able to move to read-only at dumping time
// if all the klasses are resolved. The only other field that is writable is
// the resolved_references array, which is recreated at startup time.
// But that could be moved to InstanceKlass (although a pain to access from
// assembly code). Maybe it could be moved to the cpCache which is RW.
return new (loader_data, size, false, MetaspaceObj::ConstantPoolType, THREAD) ConstantPool(tags);
}
上篇写了关于 tags实现的内容
现在解析一下size=的计算,
static int header_size() { return sizeof(ConstantPool)/HeapWordSize; } //计算结果为11
static int size(int length) { return align_object_size(header_size() + length); } //11+87 =98个 inline bool is_object_aligned(intptr_t addr) {
return addr == align_object_size(addr);//size=98
}
//在这个sizeof(ConstantPool) 计算出来的为1 不知道为什么,通过分析来得到大小
//查看分配好的常量池
(gdb) p * constant_pool
$13 = (ConstantPool) {
<Metadata> = {<MetaspaceObj> = {<No data fields>},
_vptr.Metadata = 0x7ff4c424c070 <vtable for ConstantPool+16>,
_valid = 0},
_tags = 0x7ff4c01900a8,
_cache = 0x0,
_pool_holder = 0x0,
_operands = 0x0,
_resolved_references = 0x0,
_reference_map = 0x0,
_flags = 0,
_length = 87,
_saved = {_resolved_reference_length = 0, _version = 0},
_lock = 0x7ff4bc06ec38}
(gdb) p sizeof(*constant_pool)
$15 = 88
这个通过对象来查看得到共有11项目,打印内存可以对应上
(gdb) p constant_pool
$1 = (ConstantPool *) 0x7f2563800108
(gdb) x/22x 0x7f2563800108
0x7f2563800108: 0x86b70070 0x00007f25 0x00000000 0x00000000
0x7f2563800118: 0x638000a8 0x00007f25 0x00000000 0x00000000
0x7f2563800128: 0x00000000 0x00000000 0x00000000 0x00000000
0x7f2563800138: 0x00000000 0x00000000 0x00000000 0x00000000
0x7f2563800148: 0x00000000 0x00000057 0x00000000 0x00000000
0x7f2563800158: 0x8006ec38 0x00007f25
需要特别说明的是: ConstantPool类里面有他的父类的,他的父类占用2个8字节空间,一个是虚表,一个是变量
接着
//进入重载new方法
void* MetaspaceObj::operator new(size_t size, ClassLoaderData* loader_data,
size_t word_size, bool read_only,
MetaspaceObj::Type type, TRAPS) throw() {
// Klass has it's own operator new
return Metaspace::allocate(loader_data, word_size, read_only,
type, CHECK_NULL);
}
//进入元空间进行内存分配
MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
bool read_only, MetaspaceObj::Type type, TRAPS) {
if (HAS_PENDING_EXCEPTION) {
assert(false, "Should not allocate with exception pending");
return NULL; // caller does a CHECK_NULL too
} assert(loader_data != NULL, "Should never pass around a NULL loader_data. "
"ClassLoaderData::the_null_class_loader_data() should have been used."); MetadataType mdtype = (type == MetaspaceObj::ClassType) ? ClassType : NonClassType; // Try to allocate metadata.
MetaWord* result = loader_data->metaspace_non_null()->allocate(word_size, mdtype); if (result == NULL) {
// Allocation failed.
if (is_init_completed()) {
// Only start a GC if the bootstrapping has completed. // Try to clean out some memory and retry.
result = Universe::heap()->collector_policy()->satisfy_failed_metadata_allocation(
loader_data, word_size, mdtype);
}
} if (result == NULL) {
report_metadata_oome(loader_data, word_size, mdtype, CHECK_NULL);
} // Zero initialize.
Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0); return result;
}
接着
MetaWord* Metachunk::allocate(size_t word_size) {
MetaWord* result = NULL;
// If available, bump the pointer to allocate.
if (free_word_size() >= word_size) {
result = _top;
_top = _top + word_size;
}
return result;
}
这里面设计一个指针加法, _top + 8*word_size
可以看出,_top(0x7fd4b8800108) + 98 最终等于 0x7fd4b8800418,是因为指针加法要乘 指针类型大小即8字节
通过汇编验证
(gdb) x/15i $pc
=> 0x7fdfce6ef8df <Metachunk::allocate(unsigned long)+63>: mov 0x20(%rax),%rax
0x7fdfce6ef8e3 <Metachunk::allocate(unsigned long)+67>: mov -0x20(%rbp),%rdx
0x7fdfce6ef8e7 <Metachunk::allocate(unsigned long)+71>: shl $0x3,%rdx
0x7fdfce6ef8eb <Metachunk::allocate(unsigned long)+75>: add %rax,%rdx (gdb) p *(long *) ($rax+0x20)
$15 = 140598841622792
(gdb) p/x *(long *)($rax +0x20)
$16 = 0x7fdfb802c108
(gdb) p/x *(long * )($rbp -0x20)
$17 = 0x62
接着
//看一个细节
void MetaspaceAux::inc_used(Metaspace::MetadataType mdtype, size_t words) {
// _allocated_used_words tracks allocations for
// each piece of metadata. Those allocations are
// generally done concurrently by different application
// threads so must be done atomically.
Atomic::add_ptr(words, &_allocated_used_words[mdtype]);
}
这个
static size_t _allocated_used_words[Metaspace:: MetadataTypeCount]; enum MetadataType {
ClassType,
NonClassType,
MetadataTypeCount
};
具体为
(gdb) p mdtype
$9 = Metaspace::NonClassType (gdb) p/x _allocated_used_words[mdtype]
$11 = 0x83
这里是02
那么整个过程由 0x21 变为了0x83 差值为0x62 十进制为98,和前面的98相同
这里就完成了constant_pool的创建
jvm源码解读--03 常量池的解析ConstantPool的更多相关文章
- jvm源码解读--04 常量池 常量项的解析CONSTANT_Class_info
接上篇的继续 ConstantPool* constant_pool = ConstantPool::allocate(_loader_data, length, CHECK_(nullHandle) ...
- jvm源码解读--05 常量池 常量项的解析JVM_CONSTANT_Utf8
当index=18的时候JVM_CONSTANT_Utf8 case JVM_CONSTANT_Utf8 : { cfs->guarantee_more(2, CHECK); // utf8_l ...
- JVM 源码解读之 CMS 何时会进行 Full GC
t点击上方"涤生的博客",关注我 转载请注明原创出处,谢谢!如果读完觉得有收获的话,欢迎点赞加关注. 前言 本文内容是基于 JDK 8 在文章 JVM 源码解读之 CMS GC 触 ...
- jvm源码解读--08 创建oop对象,将static静态变量放置在oop的96 offset处
之前分析的已经加载的.Class文件中都没有Static 静态变量,所以也就没这部分的解析,自己也是不懂hotspot 将静态变量放哪里去了,追踪源码之后,看清楚了整个套路,总体上来说,可以举例来说对 ...
- jvm源码解读--17 Java的wait()、notify()学习
write and debug by 张艳涛 wait()和notify()的通常用法 A线程取得锁,执行wait(),释放锁; B线程取得锁,完成业务后执行notify(),再释放锁; B线程释放锁 ...
- java基础进阶一:String源码和String常量池
作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/8046564.html 邮箱:moyi@moyib ...
- 从HotSpot VM源码看字符串常量池(StringTable)和intern()方法
引言 字符串常量池(StringTable)是JVM中一个重要的结构,它有助于避免重复创建相同内容的String对象.那么StringTable是怎么实现的?"把字符串加入到字符串常量池中& ...
- jvm源码解读--12 invokspecial指令的解读
先看代码 package com.zyt.jvmbook; public class Girl extends Person{ public Girl() { int a; } @Override p ...
- C# ArrayPool 源码解读之 byte[] 池化
一:背景 1. 讲故事最近在分析一个 dump 的过程中发现其在 gen2 和 LOH 上有不少size较大的free,仔细看了下,这些free生前大多都是模板引擎生成的html片段的byte[]数组 ...
随机推荐
- 如何下载安装Python
github博客传送门 csdn博客传送门 如何下载安装python 第一步: 在python的官网下载python版本,需要下载对应版本(在计算机-属性中查看自己是32位操作系统还是64位操作系统 ...
- sql:group by和 max
通过group by,having,max实现查询出每组里指定列中最大的内容 例如:我需要实现的功能是 获取每个模块中点击量最大的内容(表中有许多内容,内容里) 我写的查询语句如下 查询结果如下: 然 ...
- 面试热点|理解TCP/IP传输层拥塞控制算法
0x00.前言 通过本文你将了解到以下内容: 拥塞控制概念以及其背景 流量控制和拥塞控制的区别与联系 拥塞控制主要过程详解 伙伴们认真学习一下,让offer来得更猛烈些吧! 0x01.TCP/IP协议 ...
- 【模拟8.05】优美序列(线段树 分块 ST算法)
如此显然的线段树,我又瞎了眼了 事实上跟以前的奇袭很像....... 只要满足公式maxn-minn(权值)==r-l即可 所以可以考虑建两颗树,一棵节点维护位置,一棵权值, 每次从一棵树树上查询信息 ...
- SSM框架集成各配置文件
SSM框架集成各配置文件 Spring Spring MVC Mybatis 的整合SpringMVC相当于Spring的一个组件 本来就是一个家族的不存在整合的问题,所以主要就是Spring于Myb ...
- [源码解析] 深度学习分布式训练框架 horovod (6) --- 后台线程架构
[源码解析] 深度学习分布式训练框架 horovod (6) --- 后台线程架构 目录 [源码解析] 深度学习分布式训练框架 horovod (6) --- 后台线程架构 0x00 摘要 0x01 ...
- BGP路由技术
BGP路由技术 目录 一.BGP概述 1.1.自治系统 1.2.动态路由分类 1.3.BGP概念 1.4.BGP的特征 1.5.BGP工作原理 二.命令配置 2.1.BGP配置思路 2.2.命令 一. ...
- Golang封装一个加锁的Map工具包
Golang封装一个加锁的Map工具包 直接上代码了,用的是读写锁,代码如下: package utils import ( "sync" ) type BeeMap struct ...
- MetingJS 是如何配合 Aplayer 加载歌单的?
Meting.js 介绍 Meting.js 依赖 APlayer.js,扩展了 APlayer.js 的功能,能够使 APlayer.js 加载网易云音乐.QQ 音乐.虾米音乐中的歌单. 安装 &l ...
- 非静态的字段、方法或属性“System.Web.UI.Page.ClientScript.get”要求对象引用
解决Response.Write("<script>alert('修改失败,请稍后再试!');</script>");布局错误的问题 在后台CS代码(不是C ...