Klass & instanceKlass
Klass类:
Java语言层面的class对象。并为对象提供VM转发(dispath)行为。
instanceKlass类:
在VM层面表示一个Java类。
klassKlass & & instanceKlassKlass
klassKlass:
klassKlass表示类链(klass chain)的固定指针。
klassKlass的类(klass)描述就是klassKlass本身。
instanceKlassKlass:
instanceKlass的类(klass)描述
除此之外,还有instanceMirrorKlass,instanceRefKlass,methodKlass,constMethodKlass,methodDataKlass,arrayKlassKlass,objArrayKlassKlass,typeArrayKlassKlass,arrayKlass,objArrayKlass,typeArrayKlass,constantPoolKlass,constantPoolCacheKlass,compiledICHolderKlass。
oopDesc
除此之外,还有instanceOopDesc & methodOopDesc & methodDataOopDesc & arrayOopDesc & constMethodOopDesc & constantPoolOopDesc & constantPoolCacheOopDesc & objArrayOopDesc & typeArrayOopDesc & klassOopDesc & compiledICHolderOopDesc。
oop
参考hotspot\src\share\vm\oops\oopsHierarchy.hpp代码,oop声明如下:
class oop { oopDesc* _o; void register_oop(); void unregister_oop(); // friend class markOop; public: void set_obj(const void* p) { raw_set_obj(p); if (CheckUnhandledOops) register_oop(); } void raw_set_obj(const void* p) { _o = (oopDesc*)p; } oop() { set_obj(NULL); } oop(const volatile oop& o) { set_obj(o.obj()); } oop(const void* p) { set_obj(p); } oop(intptr_t i) { set_obj((void *)i); } #ifdef _LP64 oop(int i) { set_obj((void *)i); } #endif ~oop() { if (CheckUnhandledOops) unregister_oop(); } oopDesc* obj() const volatile { return _o; } // General access oopDesc* operator->() const { return obj(); } bool operator==(const oop o) const { return obj() == o.obj(); } bool operator==(void *p) const { return obj() == p; } bool operator!=(const oop o) const { return obj() != o.obj(); } bool operator!=(void *p) const { return obj() != p; } bool operator==(intptr_t p) const { return obj() == (oopDesc*)p; } bool operator!=(intptr_t p) const { return obj() != (oopDesc*)p; } bool operator<(oop o) const { return obj() < o.obj(); } bool operator>(oop o) const { return obj() > o.obj(); } bool operator<=(oop o) const { return obj() <= o.obj(); } bool operator>=(oop o) const { return obj() >= o.obj(); } bool operator!() const { return !obj(); } // Cast operator void* () const { return (void *)obj(); } operator HeapWord* () const { return (HeapWord*)obj(); } operator oopDesc* () const { return obj(); } operator intptr_t* () const { return (intptr_t*)obj(); } operator PromotedObject* () const { return (PromotedObject*)obj(); } operator markOop () const { return markOop(obj()); } operator address () const { return (address)obj(); } operator intptr_t () const { return (intptr_t)obj(); } // from javaCalls.cpp operator jobject () const { return (jobject)obj(); } // from javaClasses.cpp operator JavaThread* () const { return (JavaThread*)obj(); } #ifndef _LP64 // from jvm.cpp operator jlong* () const { return (jlong*)obj(); } #endif // from parNewGeneration and other things that want to get to the end of // an oop for stuff (like constMethodKlass.cpp, objArrayKlass.cpp) operator oop* () const { return (oop *)obj(); } };
除此之外,还有instanceOop、methodOop、methodDataOop、arrayOop、constMethodOop、constantPoolOop、constantPoolCacheOop、objArrayOop、typeArrayOop、klassOop、compiledICHolderOop。这些类的不是直接声明的,采用DEF_OOP宏定义,声明方式如下:
#define DEF_OOP(type) \ class type##OopDesc; \ class type##Oop : public oop { \ public: \ type##Oop() : oop() {} \ type##Oop(const volatile oop& o) : oop(o) {} \ type##Oop(const void* p) : oop(p) {} \ operator type##OopDesc* () const { return (type##OopDesc*)obj(); } \ type##OopDesc* operator->() const { \ return (type##OopDesc*)obj(); \ } \ }; \ DEF_OOP(instance); DEF_OOP(method); DEF_OOP(methodData); DEF_OOP(array); DEF_OOP(constMethod); DEF_OOP(constantPool); DEF_OOP(constantPoolCache); DEF_OOP(objArray); DEF_OOP(typeArray); DEF_OOP(klass); DEF_OOP(compiledICHolder);
从上面的DEF_OOP宏定义可知,这些Oop继承了oop类。
另外markOop的定义和上面的Oop不一样,定义如下:
typedef class markOopDesc* markOop;
markOop状态:
1、Inflated - just return
2、Stack-locked - coerce it to inflated
3、INFLATING - busy wait for conversion to complete
4、Neutral - aggressively inflate the object.
5、BIASED - Illegal. We should never see this
如果定义了CHECK_UNHANDLED_OOPS宏,oop定义为对应的oopDesc指针。参考hotspot\src\share\vm\oops\oopsHierarchy.hpp代码。
typedef class oopDesc* oop;
包括markOop、instanceOop、methodOop、methodDataOop、arrayOop、constMethodOop、constantPoolOop、constantPoolCacheOop、objArrayOop、typeArrayOop、klassOop、compiledICHolderOop。定义如下:
typedef class instanceOopDesc* instanceOop; typedef class methodOopDesc* methodOop; typedef class constMethodOopDesc* constMethodOop; typedef class methodDataOopDesc* methodDataOop; typedef class arrayOopDesc* arrayOop; typedef class objArrayOopDesc* objArrayOop; typedef class typeArrayOopDesc* typeArrayOop; typedef class constantPoolOopDesc* constantPoolOop; typedef class constantPoolCacheOopDesc* constantPoolCacheOop; typedef class klassOopDesc* klassOop; typedef class markOopDesc* markOop; typedef class compiledICHolderOopDesc* compiledICHolderOop;
另外除了上面的Oop,还有一个narrowOop,这个narrowOop和其他的Oop定义的不一样。参考hotspot\src\share\vm\oops\oopsHierarchy.hpp中的代码,narrowOop定义如下:
typedef juint narrowOop; // Offset instead of address for an oop within a java object
在hotspot\src\share\vm\utilities\globalDefinitions_gcc.hpp中,juint定义如下:
typedef uint32_t juint;
在hotspot\src\share\vm\utilities\globalDefinitions_sparcWorks.hpp中,juint定义如下:
typedef unsigned int juint;
在hotspot\src\share\vm\utilities\globalDefinitions_visCPP.hpp中,juint定义如下:
typedef unsigned int juint;
klassOop
jvm通过klassOop来描述一个java类, klassOop在hotspot\src\share\vm\oops\oopsHierarchy.hpp头文件中定义:
typedef class klassOopDesc* klassOop;
初始化方法<init>和<clinit>
klassOopDesc
klassOop对象布局:
[header ]
[klass_field]
[KLASS ]
klassOopDesc
class klassOopDesc : public oopDesc { public: // returns the Klass part containing dispatching behavior Klass* klass_part() const { return (Klass*)((address)this + sizeof(klassOopDesc)); } // Convenience wrapper inline oop java_mirror() const; private: // These have no implementation since klassOop should never be accessed in this fashion oop obj_field(int offset) const; volatile oop obj_field_volatile(int offset) const; void obj_field_put(int offset, oop value); void obj_field_put_raw(int offset, oop value); void obj_field_put_volatile(int offset, oop value); jbyte byte_field(int offset) const; void byte_field_put(int offset, jbyte contents); jchar char_field(int offset) const; void char_field_put(int offset, jchar contents); jboolean bool_field(int offset) const; void bool_field_put(int offset, jboolean contents); jint int_field(int offset) const; void int_field_put(int offset, jint contents); jshort short_field(int offset) const; void short_field_put(int offset, jshort contents); jlong long_field(int offset) const; void long_field_put(int offset, jlong contents); jfloat float_field(int offset) const; void float_field_put(int offset, jfloat contents); jdouble double_field(int offset) const; void double_field_put(int offset, jdouble contents); address address_field(int offset) const; void address_field_put(int offset, address contents); oop obj_field_acquire(int offset) const; void release_obj_field_put(int offset, oop value); jbyte byte_field_acquire(int offset) const; void release_byte_field_put(int offset, jbyte contents); jchar char_field_acquire(int offset) const; void release_char_field_put(int offset, jchar contents); jboolean bool_field_acquire(int offset) const; void release_bool_field_put(int offset, jboolean contents); jint int_field_acquire(int offset) const; void release_int_field_put(int offset, jint contents); jshort short_field_acquire(int offset) const; void release_short_field_put(int offset, jshort contents); jlong long_field_acquire(int offset) const; void release_long_field_put(int offset, jlong contents); jfloat float_field_acquire(int offset) const; void release_float_field_put(int offset, jfloat contents); jdouble double_field_acquire(int offset) const; void release_double_field_put(int offset, jdouble contents); address address_field_acquire(int offset) const; void release_address_field_put(int offset, address contents); };
oop
对象头
Mark Word
oopDesc
class oopDesc { friend class VMStructs; private: volatile markOop _mark; union _metadata { wideKlassOop _klass; narrowOop _compressed_klass; } _metadata; // Fast access to barrier set. Must be initialized. static BarrierSet* _bs; public: enum ConcSafeType { IsUnsafeConc = false, IsSafeConc = true }; markOop mark() const { return _mark; } markOop* mark_addr() const { return (markOop*) &_mark; } void set_mark(volatile markOop m) { _mark = m; } void release_set_mark(markOop m); markOop cas_set_mark(markOop new_mark, markOop old_mark); // Used only to re-initialize the mark word (e.g., of promoted // objects during a GC) -- requires a valid klass pointer void init_mark(); klassOop klass() const; klassOop klass_or_null() const volatile; oop* klass_addr(); narrowOop* compressed_klass_addr(); void set_klass(klassOop k); // For klass field compression int klass_gap() const; void set_klass_gap(int z); // For when the klass pointer is being used as a linked list "next" field. void set_klass_to_list_ptr(oop k); // size of object header, aligned to platform wordSize static int header_size() { return sizeof(oopDesc)/HeapWordSize; } Klass* blueprint() const; // Returns whether this is an instance of k or an instance of a subclass of k bool is_a(klassOop k) const; // Returns the actual oop size of the object int size(); // Sometimes (for complicated concurrency-related reasons), it is useful // to be able to figure out the size of an object knowing its klass. int size_given_klass(Klass* klass); // Some perm gen objects are not parseble immediately after // installation of their klass pointer. bool is_parsable(); // Some perm gen objects that have been allocated and initialized // can be changed by the VM when not at a safe point (class rededfinition // is an example). Such objects should not be examined by the // concurrent processing of a garbage collector if is_conc_safe() // returns false. bool is_conc_safe(); // type test operations (inlined in oop.inline.h) bool is_instance() const; bool is_instanceMirror() const; bool is_instanceRef() const; bool is_array() const; bool is_objArray() const; bool is_klass() const; bool is_thread() const; bool is_method() const; bool is_constMethod() const; bool is_methodData() const; bool is_constantPool() const; bool is_constantPoolCache() const; bool is_typeArray() const; bool is_javaArray() const; bool is_compiledICHolder() const; private: // field addresses in oop void* field_base(int offset) const; jbyte* byte_field_addr(int offset) const; jchar* char_field_addr(int offset) const; jboolean* bool_field_addr(int offset) const; jint* int_field_addr(int offset) const; jshort* short_field_addr(int offset) const; jlong* long_field_addr(int offset) const; jfloat* float_field_addr(int offset) const; jdouble* double_field_addr(int offset) const; address* address_field_addr(int offset) const; public: // Need this as public for garbage collection. template <class T> T* obj_field_addr(int offset) const; static bool is_null(oop obj); static bool is_null(narrowOop obj); // Decode an oop pointer from a narrowOop if compressed. // These are overloaded for oop and narrowOop as are the other functions // below so that they can be called in template functions. static oop decode_heap_oop_not_null(oop v); static oop decode_heap_oop_not_null(narrowOop v); static oop decode_heap_oop(oop v); static oop decode_heap_oop(narrowOop v); // Encode an oop pointer to a narrow oop. The or_null versions accept // null oop pointer, others do not in order to eliminate the // null checking branches. static narrowOop encode_heap_oop_not_null(oop v); static narrowOop encode_heap_oop(oop v); // Load an oop out of the Java heap static narrowOop load_heap_oop(narrowOop* p); static oop load_heap_oop(oop* p); // Load an oop out of Java heap and decode it to an uncompressed oop. static oop load_decode_heap_oop_not_null(narrowOop* p); static oop load_decode_heap_oop_not_null(oop* p); static oop load_decode_heap_oop(narrowOop* p); static oop load_decode_heap_oop(oop* p); // Store an oop into the heap. static void store_heap_oop(narrowOop* p, narrowOop v); static void store_heap_oop(oop* p, oop v); // Encode oop if UseCompressedOops and store into the heap. static void encode_store_heap_oop_not_null(narrowOop* p, oop v); static void encode_store_heap_oop_not_null(oop* p, oop v); static void encode_store_heap_oop(narrowOop* p, oop v); static void encode_store_heap_oop(oop* p, oop v); static void release_store_heap_oop(volatile narrowOop* p, narrowOop v); static void release_store_heap_oop(volatile oop* p, oop v); static void release_encode_store_heap_oop_not_null(volatile narrowOop* p, oop v); static void release_encode_store_heap_oop_not_null(volatile oop* p, oop v); static void release_encode_store_heap_oop(volatile narrowOop* p, oop v); static void release_encode_store_heap_oop(volatile oop* p, oop v); static oop atomic_exchange_oop(oop exchange_value, volatile HeapWord *dest); static oop atomic_compare_exchange_oop(oop exchange_value, volatile HeapWord *dest, oop compare_value); // Access to fields in a instanceOop through these methods. oop obj_field(int offset) const; volatile oop obj_field_volatile(int offset) const; void obj_field_put(int offset, oop value); void obj_field_put_raw(int offset, oop value); void obj_field_put_volatile(int offset, oop value); jbyte byte_field(int offset) const; void byte_field_put(int offset, jbyte contents); jchar char_field(int offset) const; void char_field_put(int offset, jchar contents); jboolean bool_field(int offset) const; void bool_field_put(int offset, jboolean contents); jint int_field(int offset) const; void int_field_put(int offset, jint contents); jshort short_field(int offset) const; void short_field_put(int offset, jshort contents); jlong long_field(int offset) const; void long_field_put(int offset, jlong contents); jfloat float_field(int offset) const; void float_field_put(int offset, jfloat contents); jdouble double_field(int offset) const; void double_field_put(int offset, jdouble contents); address address_field(int offset) const; void address_field_put(int offset, address contents); oop obj_field_acquire(int offset) const; void release_obj_field_put(int offset, oop value); jbyte byte_field_acquire(int offset) const; void release_byte_field_put(int offset, jbyte contents); jchar char_field_acquire(int offset) const; void release_char_field_put(int offset, jchar contents); jboolean bool_field_acquire(int offset) const; void release_bool_field_put(int offset, jboolean contents); jint int_field_acquire(int offset) const; void release_int_field_put(int offset, jint contents); jshort short_field_acquire(int offset) const; void release_short_field_put(int offset, jshort contents); jlong long_field_acquire(int offset) const; void release_long_field_put(int offset, jlong contents); jfloat float_field_acquire(int offset) const; void release_float_field_put(int offset, jfloat contents); jdouble double_field_acquire(int offset) const; void release_double_field_put(int offset, jdouble contents); address address_field_acquire(int offset) const; void release_address_field_put(int offset, address contents); // printing functions for VM debugging void print_on(outputStream* st) const; // First level print void print_value_on(outputStream* st) const; // Second level print. void print_address_on(outputStream* st) const; // Address printing // printing on default output stream void print(); void print_value(); void print_address(); // return the print strings char* print_string(); char* print_value_string(); // verification operations void verify_on(outputStream* st); void verify(); void verify_old_oop(oop* p, bool allow_dirty); void verify_old_oop(narrowOop* p, bool allow_dirty); // tells whether this oop is partially constructed (gc during class loading) bool partially_loaded(); void set_partially_loaded(); // locking operations bool is_locked() const; bool is_unlocked() const; bool has_bias_pattern() const; // asserts bool is_oop(bool ignore_mark_word = false) const; bool is_oop_or_null(bool ignore_mark_word = false) const; #ifndef PRODUCT bool is_unlocked_oop() const; #endif // garbage collection bool is_gc_marked() const; // Apply "MarkSweep::mark_and_push" to (the address of) every non-NULL // reference field in "this". void follow_contents(void); void follow_header(void); #ifndef SERIALGC // Parallel Scavenge void push_contents(PSPromotionManager* pm); // Parallel Old void update_contents(ParCompactionManager* cm); void follow_contents(ParCompactionManager* cm); void follow_header(ParCompactionManager* cm); #endif // SERIALGC bool is_perm() const; bool is_perm_or_null() const; bool is_scavengable() const; bool is_shared() const; bool is_shared_readonly() const; bool is_shared_readwrite() const; // Forward pointer operations for scavenge bool is_forwarded() const; void forward_to(oop p); bool cas_forward_to(oop p, markOop compare); #ifndef SERIALGC // Like "forward_to", but inserts the forwarding pointer atomically. // Exactly one thread succeeds in inserting the forwarding pointer, and // this call returns "NULL" for that thread; any other thread has the // value of the forwarding pointer returned and does not modify "this". oop forward_to_atomic(oop p); #endif // SERIALGC oop forwardee() const; // Age of object during scavenge int age() const; void incr_age(); // Adjust all pointers in this object to point at it's forwarded location and // return the size of this oop. This is used by the MarkSweep collector. int adjust_pointers(); void adjust_header(); #ifndef SERIALGC // Parallel old void update_header(); #endif // SERIALGC // mark-sweep support void follow_body(int begin, int end); // Fast access to barrier set static BarrierSet* bs() { return _bs; } static void set_bs(BarrierSet* bs) { _bs = bs; } // iterators, returns size of object #define OOP_ITERATE_DECL(OopClosureType, nv_suffix) \ int oop_iterate(OopClosureType* blk); \ int oop_iterate(OopClosureType* blk, MemRegion mr); // Only in mr. ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_DECL) #ifndef SERIALGC #define OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_iterate_backwards(OopClosureType* blk); ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_BACKWARDS_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_BACKWARDS_DECL) #endif void oop_iterate_header(OopClosure* blk); void oop_iterate_header(OopClosure* blk, MemRegion mr); // identity hash; returns the identity hash key (computes it if necessary) // NOTE with the introduction of UseBiasedLocking that identity_hash() might reach a // safepoint if called on a biased object. Calling code must be aware of that. intptr_t identity_hash(); intptr_t slow_identity_hash(); // marks are forwarded to stack when object is locked bool has_displaced_mark() const; markOop displaced_mark() const; void set_displaced_mark(markOop m); // for code generation static int mark_offset_in_bytes() { return offset_of(oopDesc, _mark); } static int klass_offset_in_bytes() { return offset_of(oopDesc, _metadata._klass); } static int klass_gap_offset_in_bytes(); };
_mark用于存对象头信息,也就是Mark Word:
volatile markOop _mark;
init_mark方法,在hotspot\src\share\vm\oops下的oop.inline.hpp头文件中:
inline void oopDesc::init_mark() { set_mark(markOopDesc::prototype_for_object(this)); }它调用hotspot\src\share\vm\oops下的markOop.inline.hpp头文件中的prototype_for_object方法得到对象头信息:
inline markOop markOopDesc::prototype_for_object(oop obj) { #ifdef ASSERT markOop prototype_header = obj->klass()->klass_part()->prototype_header(); assert(prototype_header == prototype() || prototype_header->has_bias_pattern(), "corrupt prototype header"); #endif return obj->klass()->klass_part()->prototype_header(); }
markOop
在看jvm源代码的时候,经常会看到markOop,这个在oopsHierarchy.hpp头文件中有定义, 该头文件在hotspot\src\share\vm\oops目录下,它其实是个markOopDesc的指针类型:
typedef class markOopDesc* markOop;
markOopDesc
markOopDesc用于描述java对象头定义。java对象头不是一个真的oop(oop参考另一篇介绍关于oopDesc的文章),而是通过一个word来描述。
typedef class oopDesc* oop;
在markOopDesc中也并没有定义java对象头内部结构或内存布局,而是通过markOopDesc的指针(也就是上面定义的markOop)指向对象头部,以便方便对对象头部进行操作:
// Conversion uintptr_t value() const { return (uintptr_t) this; }
markOopDesc中定义相关方法以对对象头部进行操作。
markOopDesc在markOop.hpp头文件中定义,该头文件在hotspot\src\share\vm\oops目录下:
/* * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #ifndef SHARE_VM_OOPS_MARKOOP_HPP #define SHARE_VM_OOPS_MARKOOP_HPP #include "oops/oop.hpp" // 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. class BasicLock; class ObjectMonitor; class JavaThread; class markOopDesc: public oopDesc { private: // Conversion uintptr_t value() const { return (uintptr_t) this; } public: // Constants enum { age_bits = 4, lock_bits = 2, biased_lock_bits = 1, max_hash_bits = BitsPerWord - age_bits - lock_bits - biased_lock_bits, // 11 - 4 - 2 - 1 = 4 hash_bits = max_hash_bits > 31 ? 31 : max_hash_bits, // 4 cms_bits = LP64_ONLY(1) NOT_LP64(0), // 1 epoch_bits = 2 }; // The biased locking code currently requires that the age bits be // contiguous to the lock bits. enum { lock_shift = 0, biased_lock_shift = lock_bits, // 2 age_shift = lock_bits + biased_lock_bits, // 3 cms_shift = age_shift + age_bits, // 7 hash_shift = cms_shift + cms_bits, // 8 epoch_shift = hash_shift // 8 }; enum { lock_mask = right_n_bits(lock_bits), // right_n_bits(2) = 3 lock_mask_in_place = lock_mask << lock_shift, // 3 biased_lock_mask = right_n_bits(lock_bits + biased_lock_bits), // right_n_bits(5) = 31 biased_lock_mask_in_place= biased_lock_mask << lock_shift, // 31 biased_lock_bit_in_place = 1 << biased_lock_shift, // 4 age_mask = right_n_bits(age_bits), // right_n_bits(4) = 15 age_mask_in_place = age_mask << age_shift, // 120 epoch_mask = right_n_bits(epoch_bits), // right_n_bits(2) = 3 epoch_mask_in_place = epoch_mask << epoch_shift, // 768 cms_mask = right_n_bits(cms_bits), // right_n_bits(1) = 1 cms_mask_in_place = cms_mask << cms_shift // 128 #ifndef _WIN64 ,hash_mask = right_n_bits(hash_bits), // right_n_bits(4) = 15 hash_mask_in_place = (address_word)hash_mask << hash_shift // 3840 #endif }; // Alignment of JavaThread pointers encoded in object header required by biased locking enum { biased_lock_alignment = 2 << (epoch_shift + epoch_bits) // 2048 }; #ifdef _WIN64 // These values are too big for Win64 const static uintptr_t hash_mask = right_n_bits(hash_bits); // right_n_bits(4) = 15 const static uintptr_t hash_mask_in_place = (address_word)hash_mask << hash_shift; // 3840 #endif enum { locked_value = 0, unlocked_value = 1, monitor_value = 2, marked_value = 3, biased_lock_pattern = 5 }; enum { no_hash = 0 }; // no hash value assigned enum { no_hash_in_place = (address_word)no_hash << hash_shift, no_lock_in_place = unlocked_value }; enum { max_age = age_mask }; enum { max_bias_epoch = epoch_mask }; // Biased Locking accessors. // These must be checked by all code which calls into the // ObjectSynchronizer and other code. The biasing is not understood // by the lower-level CAS-based locking code, although the runtime // fixes up biased locks to be compatible with it when a bias is // revoked. bool has_bias_pattern() const { return (mask_bits(value(), biased_lock_mask_in_place) == biased_lock_pattern); } JavaThread* biased_locker() const { assert(has_bias_pattern(), "should not call this otherwise"); return (JavaThread*) ((intptr_t) (mask_bits(value(), ~(biased_lock_mask_in_place | age_mask_in_place | epoch_mask_in_place)))); } // Indicates that the mark has the bias bit set but that it has not // yet been biased toward a particular thread bool is_biased_anonymously() const { return (has_bias_pattern() && (biased_locker() == NULL)); } // Indicates epoch in which this bias was acquired. If the epoch // changes due to too many bias revocations occurring, the biases // from the previous epochs are all considered invalid. int bias_epoch() const { assert(has_bias_pattern(), "should not call this otherwise"); return (mask_bits(value(), epoch_mask_in_place) >> epoch_shift); } markOop set_bias_epoch(int epoch) { assert(has_bias_pattern(), "should not call this otherwise"); assert((epoch & (~epoch_mask)) == 0, "epoch overflow"); return markOop(mask_bits(value(), ~epoch_mask_in_place) | (epoch << epoch_shift)); } markOop incr_bias_epoch() { return set_bias_epoch((1 + bias_epoch()) & epoch_mask); } // Prototype mark for initialization static markOop biased_locking_prototype() { return markOop( biased_lock_pattern ); } // lock accessors (note that these assume lock_shift == 0) bool is_locked() const { return (mask_bits(value(), lock_mask_in_place) != unlocked_value); } bool is_unlocked() const { return (mask_bits(value(), biased_lock_mask_in_place) == unlocked_value); } bool is_marked() const { return (mask_bits(value(), lock_mask_in_place) == marked_value); } bool is_neutral() const { return (mask_bits(value(), biased_lock_mask_in_place) == unlocked_value); } // Special temporary state of the markOop while being inflated. // Code that looks at mark outside a lock need to take this into account. bool is_being_inflated() const { return (value() == 0); } // Distinguished markword value - used when inflating over // an existing stacklock. 0 indicates the markword is "BUSY". // Lockword mutators that use a LD...CAS idiom should always // check for and avoid overwriting a 0 value installed by some // other thread. (They should spin or block instead. The 0 value // is transient and *should* be short-lived). static markOop INFLATING() { return (markOop) 0; } // inflate-in-progress // Should this header be preserved during GC? inline bool must_be_preserved(oop obj_containing_mark) const; inline bool must_be_preserved_with_bias(oop obj_containing_mark) const; // Should this header (including its age bits) be preserved in the // case of a promotion failure during scavenge? // Note that we special case this situation. We want to avoid // calling BiasedLocking::preserve_marks()/restore_marks() (which // decrease the number of mark words that need to be preserved // during GC) during each scavenge. During scavenges in which there // is no promotion failure, we actually don't need to call the above // routines at all, since we don't mutate and re-initialize the // marks of promoted objects using init_mark(). However, during // scavenges which result in promotion failure, we do re-initialize // the mark words of objects, meaning that we should have called // these mark word preservation routines. Currently there's no good // place in which to call them in any of the scavengers (although // guarded by appropriate locks we could make one), but the // observation is that promotion failures are quite rare and // reducing the number of mark words preserved during them isn't a // high priority. inline bool must_be_preserved_for_promotion_failure(oop obj_containing_mark) const; inline bool must_be_preserved_with_bias_for_promotion_failure(oop obj_containing_mark) const; // Should this header be preserved during a scavenge where CMS is // the old generation? // (This is basically the same body as must_be_preserved_for_promotion_failure(), // but takes the klassOop as argument instead) inline bool must_be_preserved_for_cms_scavenge(klassOop klass_of_obj_containing_mark) const; inline bool must_be_preserved_with_bias_for_cms_scavenge(klassOop klass_of_obj_containing_mark) const; // WARNING: The following routines are used EXCLUSIVELY by // synchronization functions. They are not really gc safe. // They must get updated if markOop layout get changed. markOop set_unlocked() const { return markOop(value() | unlocked_value); } bool has_locker() const { return ((value() & lock_mask_in_place) == locked_value); } BasicLock* locker() const { assert(has_locker(), "check"); return (BasicLock*) value(); } bool has_monitor() const { return ((value() & monitor_value) != 0); } ObjectMonitor* monitor() const { assert(has_monitor(), "check"); // Use xor instead of &~ to provide one extra tag-bit check. return (ObjectMonitor*) (value() ^ monitor_value); } bool has_displaced_mark_helper() const { return ((value() & unlocked_value) == 0); } markOop displaced_mark_helper() const { assert(has_displaced_mark_helper(), "check"); intptr_t ptr = (value() & ~monitor_value); return *(markOop*)ptr; } void set_displaced_mark_helper(markOop m) const { assert(has_displaced_mark_helper(), "check"); intptr_t ptr = (value() & ~monitor_value); *(markOop*)ptr = m; } markOop copy_set_hash(intptr_t hash) const { intptr_t tmp = value() & (~hash_mask_in_place); tmp |= ((hash & hash_mask) << hash_shift); return (markOop)tmp; } // it is only used to be stored into BasicLock as the // indicator that the lock is using heavyweight monitor static markOop unused_mark() { return (markOop) marked_value; } // the following two functions create the markOop to be // stored into object header, it encodes monitor info static markOop encode(BasicLock* lock) { return (markOop) lock; } static markOop encode(ObjectMonitor* monitor) { intptr_t tmp = (intptr_t) monitor; return (markOop) (tmp | monitor_value); } static markOop encode(JavaThread* thread, int age, int bias_epoch) { intptr_t tmp = (intptr_t) thread; assert(UseBiasedLocking && ((tmp & (epoch_mask_in_place | age_mask_in_place | biased_lock_mask_in_place)) == 0), "misaligned JavaThread pointer"); assert(age <= max_age, "age too large"); assert(bias_epoch <= max_bias_epoch, "bias epoch too large"); return (markOop) (tmp | (bias_epoch << epoch_shift) | (age << age_shift) | biased_lock_pattern); } // used to encode pointers during GC markOop clear_lock_bits() { return markOop(value() & ~lock_mask_in_place); } // age operations markOop set_marked() { return markOop((value() & ~lock_mask_in_place) | marked_value); } int age() const { return mask_bits(value() >> age_shift, age_mask); } markOop set_age(int v) const { assert((v & ~age_mask) == 0, "shouldn't overflow age field"); return markOop((value() & ~age_mask_in_place) | (((intptr_t)v & age_mask) << age_shift)); } markOop incr_age() const { return age() == max_age ? markOop(this) : set_age(age() + 1); } // hash operations intptr_t hash() const { return mask_bits(value() >> hash_shift, hash_mask); } bool has_no_hash() const { return hash() == no_hash; } // Prototype mark for initialization static markOop prototype() { return markOop( no_hash_in_place | no_lock_in_place ); } // Helper function for restoration of unmarked mark oops during GC static inline markOop prototype_for_object(oop obj); // Debugging void print_on(outputStream* st) const; // Prepare address of oop for placement into mark inline static markOop encode_pointer_as_mark(void* p) { return markOop(p)->set_marked(); } // Recover address of oop from encoded form used in mark inline void* decode_pointer() { if (UseBiasedLocking && has_bias_pattern()) return NULL; return clear_lock_bits(); } // see the definition in markOop.cpp for the gory details bool should_not_be_cached() const; // These markOops indicate cms free chunk blocks and not objects. // In 64 bit, the markOop is set to distinguish them from oops. // These are defined in 32 bit mode for vmStructs. const static uintptr_t cms_free_chunk_pattern = 0x1; // Constants for the size field. enum { size_shift = cms_shift + cms_bits, size_bits = 35 // need for compressed oops 32G }; // These values are too big for Win64 const static uintptr_t size_mask = LP64_ONLY(right_n_bits(size_bits)) NOT_LP64(0); const static uintptr_t size_mask_in_place = (address_word)size_mask << size_shift; #ifdef _LP64 static markOop cms_free_prototype() { return markOop(((intptr_t)prototype() & ~cms_mask_in_place) | ((cms_free_chunk_pattern & cms_mask) << cms_shift)); } uintptr_t cms_encoding() const { return mask_bits(value() >> cms_shift, cms_mask); } bool is_cms_free_chunk() const { return is_neutral() && (cms_encoding() & cms_free_chunk_pattern) == cms_free_chunk_pattern; } size_t get_size() const { return (size_t)(value() >> size_shift); } static markOop set_size_and_free(size_t size) { assert((size & ~size_mask) == 0, "shouldn't overflow size field"); return markOop(((intptr_t)cms_free_prototype() & ~size_mask_in_place) | (((intptr_t)size & size_mask) << size_shift)); } #endif // _LP64 }; #endif // SHARE_VM_OOPS_MARKOOP_HPP
hashCode操作,这里存的hash就是java对象的hashCode:
// hash operations intptr_t hash() const { return mask_bits(value() >> hash_shift, hash_mask); }
markOop copy_set_hash(intptr_t hash) const { intptr_t tmp = value() & (~hash_mask_in_place); tmp |= ((hash & hash_mask) << hash_shift); return (markOop)tmp; }
对象监视器
膨胀(inflate)过程
klassOop & oop 句柄
klassOop 相关句柄:KlassHandle,instanceKlassHandle
KlassHandle和instanceKlassHandle区别
oop句柄:Handle
Handle
class Handle VALUE_OBJ_CLASS_SPEC { private: oop* _handle; protected: oop obj() const { return _handle == NULL ? (oop)NULL : *_handle; } oop non_null_obj() const { assert(_handle != NULL, "resolving NULL handle"); return *_handle; } public: // Constructors Handle() { _handle = NULL; } Handle(oop obj); #ifndef ASSERT Handle(Thread* thread, oop obj); #else // Don't inline body with assert for current thread Handle(Thread* thread, oop obj); #endif // ASSERT // General access oop operator () () const { return obj(); } oop operator -> () const { return non_null_obj(); } bool operator == (oop o) const { return obj() == o; } bool operator == (const Handle& h) const { return obj() == h.obj(); } // Null checks bool is_null() const { return _handle == NULL; } bool not_null() const { return _handle != NULL; } // Debugging void print() { obj()->print(); } // Direct interface, use very sparingly. // Used by JavaCalls to quickly convert handles and to create handles static data structures. // Constructor takes a dummy argument to prevent unintentional type conversion in C++. Handle(oop *handle, bool dummy) { _handle = handle; } // Raw handle access. Allows easy duplication of Handles. This can be very unsafe // since duplicates is only valid as long as original handle is alive. oop* raw_value() { return _handle; } static oop raw_resolve(oop *handle) { return handle == NULL ? (oop)NULL : *handle; } };
jobject
class _jobject {}; typedef _jobject *jobject;但在C语言环境中,它被定义为_jobject类型的指针。
struct _jobject; typedef struct _jobject *jobject;
jobject handle = ... oop* ptr = (oop*)handle;
相关推荐
- **句柄访问**:每个对象都有一个句柄指向其对象头,对象头中包含实际的数据和元数据。 - **直接指针**:对象头中直接存放对象数据的地址,这种方式减少了指针寻址的开销。 #### 8. 如何判断对象已经死亡? 判断...
- **句柄访问**: 通过句柄池中的句柄来访问对象实例数据。 - **直接指针**: 直接通过对象的地址访问对象实例数据。 4. **内存溢出(Out Of Memory Error, OOM)**: - **堆溢出**:对象实例数量超过最大堆容量限制...
优缺点:句柄引用,当对象实例发生改变的时候,只需要改掉句柄对实例对象物理地址的引用即可,修改比较方便与快捷缺点,但是确定是对象的分配比较频繁,因此获取对象是一个频繁的动作,使用直接指针访问,这样的性能...
1. **句柄访问**:在Java堆之外维护一个句柄池,句柄中包含了对象实例数据与类型数据各自具体的内存地址信息。 2. **直接指针**:对象头中包含了对象的实例数据与类型数据的地址信息,这种方式的访问速度更快。 ###...
### JVM底层原理——类加载子系统详解 #### 一、引言 Java虚拟机(JVM)作为Java程序运行的基础环境,其内部结构复杂且功能强大。本文将基于“JVM底层原理课件PPT”中关于类加载子系统的介绍进行深入解析。类加载子...
- **对象访问定位**:通过栈上的引用访问堆上的对象,有两种方式:句柄访问和直接指针访问。 垃圾收集器是JVM的关键组件,负责自动回收不再使用的内存。它主要通过两种算法来判断对象是否死亡: 1. **引用计数算法...
2. **句柄定位**:这种方式维护一个句柄池,对象引用指向句柄池中的地址,句柄池再指向实际对象和类信息。这种方式在GC时只需更改句柄池,但访问速度较慢。 **对象内存布局** 1. **对象头**:包含Mark Word(用于...
JVM提供了两种主要的访问方式:句柄访问和直接指针访问。 #### 4. 垃圾回收(GC) 垃圾回收是JVM自动管理内存的关键机制之一,主要包括以下几种算法: - **引用计数算法**:通过维护对象的引用计数来判断对象是否...
句柄访问通过句柄池访问对象数据,reference稳定;直接指针访问速度快,但reference会随对象移动。 理解以上知识点对于优化Java程序性能、避免内存泄漏和提高应用稳定性具有重要意义。开发者需要深入理解JVM的工作...
- **句柄访问**(HotSpot 默认):在这种模式下,JVM为每个对象分配一个句柄,句柄是一个包含对象实例数据地址和类型数据地址的结构。当程序访问对象时,通过句柄来间接访问,这样做的好处是对象移动时,只需要更新...
4. 如果该类已经被加载,则开始给该对象在JVM的堆中分配内存。 5. 虚拟机初始化操作,虚拟机对分配的空间初始化为零值。 6. 执行init方法,初始化对象的属性,至此对象被创建完成。 7. java虚拟机栈中的Reference...
- **对象访问定位**:句柄和直接指针两种方式,影响内存布局和访问速度。 4. **垃圾收集**: - **判断对象是否已死**:引用计数法和可达性分析算法(GCRoots)。 - **垃圾收集算法**:标记-清除、复制、标记-...
- **句柄访问:** 每个对象都有一个句柄指向方法区的对象类型数据,另一个指向对象的数据。 - **直接指针:** 直接使用对象头中的地址来定位对象的数据。 #### 内存溢出异常 **内存溢出(Memory Overflow):** 当程序...
- **对象访问定位**:通过句柄或直接指针方式找到对象实例。 4. **垃圾收集(GC)判定方法**: - **引用计数法**:简单但无法处理循环引用问题,JVM未采用。 - **可达性分析法(引用链法)**:通过GC Roots进行...
- 局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等于...,也可能是指向一个代表对象的句柄或者其他与此对象相关的位置)...
这通过`GetMethodID`实现,需要提供类的句柄、方法的签名以及方法名。例如,调用静态方法`public static void myMethod()`,签名应为`(V)`。 3. **调用Java方法**:有了方法ID,就可以使用`CallVoidMethod`, `...
以下是对JVM运行时数据区、常见异常、对象创建过程以及对象访问定位等知识点的详细解释: 1. **JVM运行时数据区**: - **程序计数器**:每个线程都有自己的程序计数器,用于记录当前线程正在执行的字节码指令的...
对象的内存分配依赖于JVM的内存管理机制,常见的访问定位方式包括使用句柄和直接指针两种。 GC(垃圾回收)是JVM自动管理内存的关键机制,它能自动回收不再使用的对象占用的内存空间。JVM中垃圾回收的判定方法主要...