jvm源码解读--15 oop对象详解

时间:2022-09-27 16:04:50
(gdb) p obj
$15 = (oopDesc *) 0xf3885d08
(gdb) p * obj
$16 = {
_mark = 0x70dea4e01,
_metadata = {
_klass = 0x2000070e,
_compressed_klass = 536872718
},
static _bs = 0x7f658801eea8
}

1.介绍oo对象

现在先看最长使用的oop对象的定义,jvm的二分模型就是oop和class,所有的对象在hotspot层全被具体化成了oop对象,

oop的结构很简单,表示一个hotspot对象,也可以理解为一个java对象(不过包了一层handle才是java对象), 比如在java中创建一个对象

Student xm=new Student();

xm.name="小明";

xm.age=18;

这个xm就是oop,,这个oop被放在堆中,代表的就是xm这个对象,那么这个对象有成员变量name,age,那么oop对象在内存中的

oop对象
内存地址64位 _mark属性
内存地址32(压缩指针)或64 _metadata,指向class对象
内存地址 "小明"oop对象指针
内存地址 18,int类型数值

那么整个对象的大小包括了oop对象头大小为12字节(压缩)+成员变量1+成员变量2..,其中包括父类的成员变量的值,不包括static变量的值(static变量保存在class的java_mirror属性中)

如果新建一个oop对象,分配内存需要计算oop大小,那么oop的size()实际上是取值oop对应的元对象class的_layout_helper 的大小

贴一个class对象

(gdb) p k
$87 = (InstanceKlass *) 0x100060030
(gdb) p * k
$88 = (InstanceKlass) {
<Klass> = {
<Metadata> = {
<MetaspaceObj> = {<No data fields>},
members of Metadata:
_vptr.Metadata = 0x7f5aa945e590 <vtable for InstanceKlass+16>,
_valid = 0
},
members of Klass:
_layout_helper = 24,
_super_check_offset = 56,
_name = 0x7f5aa014b5d8,
_secondary_super_cache = 0x0,
_secondary_supers = 0x7f5aa5399090,
_primary_supers = {0x100000f30, 0x100060030, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
_java_mirror = 0xd758fc70,
_super = 0x100000f30,
_subklass = 0x0,
_next_sibling = 0x1000471a8,
_next_link = 0x0,
_class_loader_data = 0x7f5aa0153768,
_modifier_flags = 1,
_access_flags = {
_flags = 2097185
},
_last_biased_lock_bulk_revocation_time = 0,
_prototype_header = 0x5,
_biased_lock_revocation_count = 0,
_modified_oops = 1 '\001',
_accumulated_modified_oops = 0 '\000'
},
members of InstanceKlass:
static _total_instanceKlass_count = 415,
_annotations = 0x0,
_array_klasses = 0x0,
_constants = 0x7f5aa5799080,
_inner_classes = 0x7f5aa5399060,
_source_debug_extension = 0x0,
_array_name = 0x0,
_nonstatic_field_size = 2,
_static_field_size = 1,
_generic_signature_index = 0,
_source_file_name_index = 69,
_static_oop_field_count = 0,
_java_fields_count = 3,
_nonstatic_oop_map_size = 1,
_is_marked_dependent = false,
_misc_flags = 6,
_minor_version = 0,
_major_version = 51,
_init_thread = 0x0,
_vtable_len = 5,
_itable_len = 2,
_oop_map_cache = 0x0,
_member_names = 0x0,
_jni_ids = 0x0,
_methods_jmethod_ids = 0x0,
_dependencies = 0x0,
_osr_nmethods_head = 0x0,
_breakpoints = 0x0,
_previous_versions = 0x0,
_cached_class_file = 0x0,
_idnum_allocated_count = 3,
_init_state = 1 '\001',
_reference_type = 0 '\000',
_jvmti_cached_class_field_map = 0x0,
_verify_count = 0,
_methods = 0x7f5aa5799338,
_default_methods = 0x0,
_local_interfaces = 0x7f5aa5399090,
_transitive_interfaces = 0x7f5aa5399090,
_method_ordering = 0x7f5aa5399048,
_default_vtable_indices = 0x0,
_fields = 0x7f5aa5799308
}

这个类为

(gdb) p name->as_utf8()
$80 = 0x7f5aa0009c88 "com/test/Test"

2.介绍mark成员变量

这里先贴出来注释的东西

// The markOop describes the header of an object.
//
// Note that the mark is not a real oop but just a word.
// It is placed in the oop hierarchy for historical reasons.
//
// Bit-format of an object header (most significant first, big endian layout below):
//
// 32 bits:
// --------
// hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)
// JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object)
// size:32 ------------------------------------------>| (CMS free block)
// PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
//
// 64 bits:
// --------
// unused:25 hash:31 -->| unused:1 age:4 biased_lock:1 lock:2 (normal object)
// JavaThread*:54 epoch:2 unused:1 age:4 biased_lock:1 lock:2 (biased object)
// PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
// size:64 ----------------------------------------------------->| (CMS free block)
//
// unused:25 hash:31 -->| cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && normal object)
// JavaThread*:54 epoch:2 cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && biased object)
// narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)
// unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)
//
// - hash contains the identity hash value: largest value is
// 31 bits, see os::random(). Also, 64-bit vm's require
// a hash value no bigger than 32 bits because they will not
// properly generate a mask larger than that: see library_call.cpp
// and c1_CodePatterns_sparc.cpp.
//
// - the biased lock pattern is used to bias a lock toward a given
// thread. When this pattern is set in the low three bits, the lock
// is either biased toward a given thread or "anonymously" biased,
// indicating that it is possible for it to be biased. When the
// lock is biased toward a given thread, locking and unlocking can
// be performed by that thread without using atomic operations.
// When a lock's bias is revoked, it reverts back to the normal
// locking scheme described below.
//
// Note that we are overloading the meaning of the "unlocked" state
// of the header. Because we steal a bit from the age we can
// guarantee that the bias pattern will never be seen for a truly
// unlocked object.
//
// Note also that the biased state contains the age bits normally
// contained in the object header. Large increases in scavenge
// times were seen when these bits were absent and an arbitrary age
// assigned to all biased objects, because they tended to consume a
// significant fraction of the eden semispaces and were not
// promoted promptly, causing an increase in the amount of copying
// performed. The runtime system aligns all JavaThread* pointers to
// a very large value (currently 128 bytes (32bVM) or 256 bytes (64bVM))
// to make room for the age bits & the epoch bits (used in support of
// biased locking), and for the CMS "freeness" bit in the 64bVM (+COOPs).
//
// [JavaThread* | epoch | age | 1 | 01] lock is biased toward given thread
// [0 | epoch | age | 1 | 01] lock is anonymously biased
//
// - the two lock bits are used to describe three states: locked/unlocked and monitor.
//
// [ptr | 00] locked ptr points to real header on stack
// [header | 0 | 01] unlocked regular object header
// [ptr | 10] monitor inflated lock (header is wapped out)
// [ptr | 11] marked used by markSweep to mark an object
// not valid at any other time
//
// We assume that stack/thread pointers have the lowest two bits cleared.

// 64 bits:
// --------
// unused:25 hash:31 -->| unused:1 age:4 biased_lock:1 lock:2 (normal object)

unused:25  hash:31  unused:1   age:4 biased_lock:1  lock:2
  哈希值   gc存活年度 偏向锁 状态
 

111 0000 1101 1110 1010 0100 1110

(70D EA4E)

0 000 0 0 01

_mark = 0x70dea4e01,变为二进制

111 0000 1101 1110 1010 0100 1110 0000 0001

对于lock:2的取值不同,代表的意义不同,当为01的时候,不锁,那么按照上表表头来解析,如果是11,那么是在gc的时候会将已经已经复制到to区域的oop的,在没有清除之前,他会在eden区域,这个时候会将eden区域的老oop对象后两位设置为11; (used by markSweep to mark an object not valid at any other time)

//    [JavaThread* | epoch | age | 1 | 01]       lock is biased toward given thread
// [0 | epoch | age | 1 | 01] lock is anonymously biased
//
// - the two lock bits are used to describe three states: locked/unlocked and monitor.
//
// [ptr | 00] locked ptr points to real header on stack
// [header | 0 | 01] unlocked regular object header
// [ptr | 10] monitor inflated lock (header is wapped out)
// [ptr | 11] marked used by markSweep to mark an object
// not valid at any other time

那么现在,现在执行new Object().hasCode()方法就是,取得oop的hash值的执行过程为

JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle))
JVMWrapper("JVM_IHashCode");
// as implemented in the classic virtual machine; return 0 if object is NULL
return handle == NULL ? 0 : ObjectSynchronizer::FastHashCode (THREAD, JNIHandles::resolve_non_null(handle)) ;
JVM_END

进入

intptr_t ObjectSynchronizer::FastHashCode (Thread * Self, oop obj) {
if (UseBiasedLocking) {
// thread-local storage.
if (obj->mark()->has_bias_pattern()) {
// Box and unbox the raw reference just in case we cause a STW safepoint.
Handle hobj (Self, obj) ;
// Relaxing assertion for bug 6320749.
assert (Universe::verify_in_progress() ||
!SafepointSynchronize::is_at_safepoint(),
"biases should not be seen by VM thread here");
BiasedLocking::revoke_and_rebias(hobj, false, JavaThread::current());
obj = hobj() ;
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
}
} ObjectMonitor* monitor = NULL;
markOop temp, test;
intptr_t hash;
markOop mark = ReadStableMark (obj); // object should remain ineligible for biased locking
assert (!mark->has_bias_pattern(), "invariant") ; if (mark->is_neutral()) {
hash = mark->hash(); // this is a normal header
if (hash) { // if it has hash, just return it
return hash;
}
hash = get_next_hash(Self, obj); // allocate a new hash code
temp = mark->copy_set_hash(hash); // merge the hash code into header
// use (machine word version) atomic operation to install the hash
test = (markOop) Atomic::cmpxchg_ptr(temp, obj->mark_addr(), mark);
if (test == mark) {
return hash;
}

接着

  // hash operations
intptr_t hash() const {
return mask_bits(value() >> hash_shift, hash_mask);
}

看 (gdb) p/d hash_shift   $18 = 8

那么  uintptr_t value() const { return (uintptr_t) this; } 那么就是将0x70dea4e01,右移8位

在看掩码

(gdb) p/x hash_mask
$20 = 7FFF FFFF

二进制位01111111111111111111111111111111,那么31位1,就和hash的31为对应上了

那么打印一下计算结果

(gdb) p/x hash
$22 = 0x70dea4e

所以:这个值和(70D EA4E) 表格中的hash值是一样的

jvm源码解读--15 oop对象详解的更多相关文章

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

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

  2. JVM源码分析之Java对象头实现

    原创申明:本文由公众号[猿灯塔]原创,转载请说明出处标注 “365篇原创计划”第十一篇. 今天呢!灯塔君跟大家讲: JVM源码分析之Java对象头实现 HotSpot虚拟机中,对象在内存中的布局分为三 ...

  3. jvm源码解读--17 Java的wait&lpar;&rpar;、notify&lpar;&rpar;学习

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

  4. object -c OOP &comma; 源码组织 ,Foundation 框架 详解1

     object -c  OOP ,  源码组织  ,Foundation 框架 详解1 1.1 So what is OOP? OOP is a way of constructing softwar ...

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

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

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

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

  7. jvm源码解读--13 gc&lowbar;root中的栈中oop的mark 和copy 过程分析

    粘贴源码 package com.test; import java.util.Random; public class Test { static int number=12; private in ...

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

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

  9. jvm源码解读--11 ldc指令的解读

    写一个java文件 public static void main(String[] args) { String str1="abc"; String str2 ="a ...

随机推荐

  1. 调用约定&lowbar;&lowbar;cdecl和&lowbar;&lowbar;stdcall

    首先,__cdecl,c declaration,C风格声明.或者 c default calling(笔者瞎编的).(那么问题来了,为什么PASCAL风格被称为std?) 调用约定的内容包括三点:参 ...

  2. CDN技术发展趋势

    智能化 存储智能化 关键技术点:文件分片热度的判断策略,跨节点快速文件调度 存储向以文件切片为基础的全网共享存储发展:把一个整片切成n个小块,按用户访问热度分散存储在不同节点.当用户访问的时候,由边缘 ...

  3. Oracle 11g ORA-00845&colon; MEMORY&lowbar;TARGET not supported on this system

    启动Oracle 11gR2后报错:ORA-00845 rac1:/home/oracle> sqlplus / as sysdba; SQL*Plus: Release 11.2.0.3.0 ...

  4. GDB---Oracle Function Call List

    http://yong321.freeshell.org/Oracle Function Call List 1. Oracle function call list If you want to s ...

  5. python的Flask 介绍

    Flask 介绍 知识点 微框架.WSGI.模板引擎概念 使用 Flask 做 web 应用 模板的使用 根据 URL 返回特定网页 实验步骤 1. 什么是 Flask? Flask 是一个 web ...

  6. jQuery实现淘宝轮播图

    我爱撸码,撸码使我感到快乐大家好,我是Counter今天给大家分享的是利用jQuery来实现淘宝轮播图,揭开这层神秘的面纱,CSS样式就不做过多的赘述了,主要就是实现的原理,也就是jQuery,老样子 ...

  7. 禁止 pdf 下载、打印的方法

    https://blog.csdn.net/For_GG/article/details/78616063 https://blog.csdn.net/xiangcns/article/details ...

  8. C&num;基础&lpar;string&rpar;

    https://msdn.microsoft.com/zh-cn/library/84787k22(v=vs.110).aspx 1.Compare基本方法 public static int Com ...

  9. &lbrack;转载&rsqb; 虚拟机下面安装windows&plus;oracle ASM的过程

    转帖:https://www.2cto.com/database/201303/195261.html 最开始的时候 我找了一个挺好的教程 安装过 但是已经找不到了,先转载一下这个内容,后续再测试完善 ...

  10. 修改&period;net core MVC默认端口

    默认端口是5000,更改端口修改launchSettings.json.如图: