zoukankan      html  css  js  c++  java
  • jvm源码解读--15 oop对象详解

    (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 '01',
                        _accumulated_modified_oops = 0 '00'
            },
            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 '01',
            _reference_type = 0 '00',
            _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值是一样的

  • 相关阅读:
    【jQuery基础学习】03 jQuery中的事件与动画
    【jQuery基础学习】02 jQuery的DOM操作
    【jQuery基础学习】01 jQuery选择器
    【jQuery基础学习】00 序
    【JS复习笔记】07 复习感想
    【JS复习笔记】06 方法
    洛谷P1067 多项式输出 NOIP 2009 普及组 第一题
    嵊州D6T2 城市 city
    博弈论小结
    嵊州D2T4 十七个中毒的英国人 poisoning
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/14782184.html
Copyright © 2011-2022 走看看