接上篇的继续

  ConstantPool* constant_pool = ConstantPool::allocate(_loader_data, length,
CHECK_(nullHandle));
_cp = constant_pool; // save in case of errors
constantPoolHandle cp (THREAD, constant_pool); // parsing constant pool entries
parse_constant_pool_entries(length, CHECK_(nullHandle));

分析橘色的

上面是一个构造方法

定义中是带宏的,先看gdb打印类
(gdb) ptype cp
type = /* real type = constantPoolHandle */
class constantPoolHandle : public StackObj {
private:
ConstantPool *_value;
Thread *_thread; protected:
ConstantPool * obj(void) const;
ConstantPool * non_null_obj(void) const;
public:
constantPoolHandle(void);
constantPoolHandle(ConstantPool *);
constantPoolHandle(Thread *, ConstantPool *);
constantPoolHandle(const constantPoolHandle &);
constantPoolHandle & operator=(const constantPoolHandle &);
~constantPoolHandle();
void remove(void);
ConstantPool * operator()(void) const;
ConstantPool * operator->(void) const;
bool operator==(ConstantPool *) const;
bool operator==(const constantPoolHandle &) const;
bool is_null(void) const;
bool not_null(void) const;
}

接着看宏定义

在程序中是用宏定义的
DEF_METADATA_HANDLE_FN(constantPool, ConstantPool) 看下面的宏定义
// Constructors for metadata handles
#define DEF_METADATA_HANDLE_FN(name, type) \\这里是初始化列表的构造方法,
inline name##Handle::name##Handle(type* obj) : _value(obj), _thread(NULL) {
if (obj != NULL) { \
assert(((Metadata*)obj)->is_valid(), "obj is valid"); \
_thread = Thread::current(); \
assert (_thread->is_in_stack((address)this), "not on stack?"); \
_thread->metadata_handles()->push((Metadata*)obj); \
} \
} \
inline name##Handle::name##Handle(Thread* thread, type* obj) : _value(obj), _thread(thread) { \
if (obj != NULL) { \
assert(((Metadata*)obj)->is_valid(), "obj is valid"); \
assert(_thread == Thread::current(), "thread must be current"); \
assert (_thread->is_in_stack((address)this), "not on stack?"); \
_thread->metadata_handles()->push((Metadata*)obj); \
} \
}

在看实际解析

(gdb) p cp
$2 = (constantPoolHandle) {
<StackObj> = {<AllocatedObj> = {_vptr.AllocatedObj = 0x7f2586b44390 <vtable for constantPoolHandle+16>}, <No data fields>},
_value = 0x7f2563800108,
_thread = 0x7f258000b800}
接着进入的常量池条目解析
// parsing constant pool entries
parse_constant_pool_entries(length, CHECK_(nullHandle)); //经典的 对象和指针
ClassFileStream* cfs0 = stream();
ClassFileStream cfs1 = *cfs0;
ClassFileStream* cfs = &cfs1;

先提供些定义

enum {
JVM_CONSTANT_Utf8 = 1,
JVM_CONSTANT_Unicode, /* unused */
JVM_CONSTANT_Integer, // 3
JVM_CONSTANT_Float, // 4
JVM_CONSTANT_Long,
JVM_CONSTANT_Double,
JVM_CONSTANT_Class,
JVM_CONSTANT_String,
JVM_CONSTANT_Fieldref,
JVM_CONSTANT_Methodref,
JVM_CONSTANT_InterfaceMethodref,
JVM_CONSTANT_NameAndType,
JVM_CONSTANT_MethodHandle = 15, // JSR 292
JVM_CONSTANT_MethodType = 16, // JSR 292
//JVM_CONSTANT_(unused) = 17, // JSR 292 early drafts only
JVM_CONSTANT_InvokeDynamic = 18, // JSR 292
JVM_CONSTANT_ExternalMax = 18 // Last tag found in classfiles
};

还有

CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];
} CONSTANT_Integer_info {
u1 tag;
u4 bytes;
} CONSTANT_Float_info {
u1 tag;
u4 bytes;
} CONSTANT_Long_info {
u1 tag;
u4 high_bytes;
u4 low_bytes;
} CONSTANT_Double_info {
u1 tag;
u4 high_bytes;
u4 low_bytes;
} CONSTANT_Class_info {
u1 tag;
u2 name_index;
} CONSTANT_String_info {
u1 tag;
u2 string_index;
} CONSTANT_Fieldref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
} CONSTANT_Methodref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
} CONSTANT_InterfaceMethodref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
} CONSTANT_NameAndType_info {
u1 tag;
u2 name_index;
u2 descriptor_index;
} CONSTANT_MethodHandle_info {
u1 tag;
u1 reference_kind;
u2 reference_index;
} CONSTANT_MethodType_info {
u1 tag;
u2 descriptor_index;
} CONSTANT_InvokeDynamic_info {
u1 tag;
u2 bootstrap_method_attr_index;
u2 name_and_type_index;
}

进入函数

 // parsing  Index 0 is unused
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 :
{
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;
....
}

蓝色的过程就是取出tag的值

看执行前

先看下cfs 对象
(gdb) p cfs
$4 = (ClassFileStream *) 0x7f2587845460
(gdb) p * cfs
$5 = (ClassFileStream) {<ResourceObj> = {<AllocatedObj> = {_vptr.AllocatedObj = 0x7f2586b588b0 <vtable for ClassFileStream+16>}, _allocation_t = {18446604274545437599, 0}},
_buffer_start = 0x7f258000ea28 "\312\376\272\276",
_buffer_end = 0x7f258000f0ee "\253\253\253\253\253\253\253\253\253\253\260\210\265\206%\177",
_current = 0x7f258000ea32 "\a",
_source = 0x7f258006eb98 "/home/atzhang/atzhang/openjdksource/openjdk8/openjdk/build/linux-x86_64-normal-server-slowdebug/jdk/classes", _need_verify = false} (gdb) x/10x cfs->_current
0x7f258000ea32: 0x0a3a0007 0x3b000100 0x0012000a 0x3d000a3c
0x7f258000ea42: 0x000a3e00 0x083f0001 0x000a4000 0x0a410012
0x7f258000ea52: 0x43004200 0x0001000a

那么取出来u1 就是07

进入switch tag=7 对应的是

CONSTANT_Class_info {
u1 tag;
u2 name_index;
}
与下面的逻辑相应
      case JVM_CONSTANT_Class :
{
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);
}

取u2 =58  对应内存标注蓝色的0x3a

进入黄色函数之前的定义有

enum {
// See jvm.h for shared JVM_CONSTANT_XXX tags
// NOTE: replicated in SA in vm/agent/sun/jvm/hotspot/utilities/ConstantTag.java
// Hotspot specific tags
JVM_CONSTANT_Invalid = 0, // For bad value initialization
JVM_CONSTANT_InternalMin = 100, // First implementation tag (aside from bad value of course)
JVM_CONSTANT_UnresolvedClass = 100, // Temporary tag until actual use
JVM_CONSTANT_ClassIndex = 101, // Temporary tag while constructing constant pool
JVM_CONSTANT_StringIndex = 102, // Temporary tag while constructing constant pool
JVM_CONSTANT_UnresolvedClassInError = 103, // Error tag due to resolution error
JVM_CONSTANT_MethodHandleInError = 104, // Error tag due to resolution error
JVM_CONSTANT_MethodTypeInError = 105, // Error tag due to resolution error
JVM_CONSTANT_InternalMax = 105 // Last implementation tag
};

进入黄色函数

// For temporary use while constructing constant pool
void klass_index_at_put(int which, int name_index) {
tag_at_put(which, JVM_CONSTANT_ClassIndex);
*int_at_addr(which) = name_index;
} void tag_at_put(int which, jbyte t) { tags()->at_put(which, t); }
Array<u1>* tags() const { return _tags; }
void at_put(const int i, const T& x) { assert(i >= 0 && i< _length, err_msg("oob: 0 <= %d < %d", i, _length)); _data[i] = x; }

能看到粉色函数是将tags数组索引为1的值设为了101 (JVM_CONSTANT_ClassIndex = 101)

使用内存验证

执行前
(gdb) x/10x _data
0x7f25638000ac: 0x00000000 0x00000000 0x00000000 0x00000000
0x7f25638000bc: 0x00000000 0x00000000 0x00000000 0x00000000
0x7f25638000cc: 0x00000000 0x00000000 执行后
(gdb) x/10x _tags._data
0x7f25638000ac: 0x00006500 0x00000000 0x00000000 0x00000000
0x7f25638000bc: 0x00000000 0x00000000 0x00000000 0x00000000
0x7f25638000cc: 0x00000000 0x00000000

进入灰色函数

jint* int_at_addr(int which) const {
assert(is_within_bounds(which), "index out of bounds");
return (jint*) &base()[which];
} intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(ConstantPool)); }

解析这个,

//解释  (gdb) p this
//$16 = (const ConstantPool * const) 0x7f2563800108
这里要转换,转换为(char*)指针类型的做加法 + {sizeof(ConstantPool)=88} 就是加88个字节,要是 (long*)类型的加法就会+88*8 了
(gdb) p (jint*) &base()[0]
$20 = (jint *) 0x7f2563800160
(gdb) p (jint*) &base()[which]
$19 = (jint *) 0x7f2563800168 ,这里which等于1,所以移动了8位
实际实现的就是将index=58 存放到了0x7f2563800168,这个地方了,这个地方之前,内存分配的时候为87个变量每个变量分配了一个8字节的空间
那么就是将58 这个变量放到了那个地址中

内存情况
(gdb) p *0x7f2563800168
$21 = 0
执行后
(gdb) p *0x7f2563800168
$22 = 58
 

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

  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源码解读--05 常量池 常量项的解析JVM_CONSTANT_Utf8

    当index=18的时候JVM_CONSTANT_Utf8 case JVM_CONSTANT_Utf8 : { cfs->guarantee_more(2, CHECK); // utf8_l ...

  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. MySQL零散知识点(02)

    存储过程 存储过程包含了一系列可执行的sql语句,存储过程存放于MySQL中,通过调用它的名字可以执行其内部的一堆sql,类似于python中的自定义函数 基本使用 delimiter $$ crea ...

  2. SpringCloud(1)生态与简绍

    一:微服务架构简绍学习目标 1.技术架构的演变,怎么一步步到微服务的:2.什么是微服务,优点与缺点  :3.SOA(面向服务)与MicroServices(微服务)的区别 :4.Dubbo 与Spri ...

  3. Mysql优化(出自官方文档) - 第七篇

    Mysql优化(出自官方文档) - 第七篇 目录 Mysql优化(出自官方文档) - 第七篇 Optimizing Data Change Statements 1 Optimizing INSERT ...

  4. 同事内推的那位Linux C/C++后端开发同学面试没过......

    最近同事内推了一位 Linux C/C++ 后端开发的同学到我们公司面试,我是一面的面试官,很遗憾这位工作了两年的同学面试表现不是很好.我问了如下一些问题: "redis持久化机制,redi ...

  5. Vue(12)组件的组织结构和组件注册

    组件的组织 通常一个应用会以一棵嵌套的组件树的形式来组织: 例如,你可能会有页头.侧边栏.内容区等组件,每个组件又包含了其它的像导航链接.博文之类的组件. 为了能在模板中使用,这些组件必须先注册以便 ...

  6. To_Heart—题解——AT2165

    这是一篇解题报告 首先,看到标签,考虑二分答案. 我们二分答案(即塔顶的值),把大于或等于这个值的变为1,否则变为0. 很容易发现,如果塔顶的答案是1,那么就说明值可以更大,否则相反. 复制一波样例 ...

  7. 手把手教会你远程Linux虚拟机连接以及配置pytorch环境。

    出一期用于连接远程Ubuntu系统并配置pytorch环境的教学.2021-07-07 13:35:57- 现在的矿难导致显卡大幅度的涨价对很多要做深度学习领域的小伙伴们非常的不友好,配置设备固然要掏 ...

  8. OpenMVG 系列 (1):入门简介

    1  OpenMVG 简介  全称 Open Multiple View Geometry,是法国人 Pierre Moulon 读博期间开源的一个 C++ 库 最早版本 OpenMVG 0.1 是 ...

  9. Mybatis学习(8)动态sql语句

    Mybatis 的动态sql语句是基于OGNL表达式的.可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类: 1. if 语句 (简单的条件判断) 2. ...

  10. buu 刮开有奖

    一.查壳, 二.拖入ida,分析 直接搜字符串完全没头绪,在看了大佬的wp才找到了,关键函数. 明显那个String就是我们要求的flag,要开始分析程序. 字符串长度为8,同时这个函数对字符串进行了 ...