`
lobin
  • 浏览: 425845 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JVM: 类、对象以及对象句柄

 
阅读更多

 

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;
}

 

 

 

对象监视器

ObjectMonitor
 

膨胀(inflate)过程

 

klassOop & oop 句柄

klassOop 相关句柄:KlassHandle,instanceKlassHandle

 

KlassHandle和instanceKlassHandle区别

 

 

oop句柄:Handle

 

Handle

Handle是在thread-local的handle area中分配的。
参考hotspot\src\share\vm\runtime\handles.hpp代码,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; }
};
 
Handle、KlassHandle、instanceHandle、methodHandle、constMethodHandle、methodDataHandle、arrayHandle、constantPoolHandle、constantPoolCacheHandle、objArrayHandle、typeArrayHandle、instanceKlassHandle、methodKlassHandle、constMethodKlassHandle、klassKlassHandle、arrayKlassKlassHandle、objArrayKlassKlassHandle、typeArrayKlassKlassHandle、arrayKlassHandle、typeArrayKlassHandle、objArrayKlassHandle、constantPoolKlassHandle、constantPoolCacheKlassHandle
除了上面的Handle,还有个特殊句柄jobject,和上面的Handle不同的是,它没有继承Handle类。其定义在后面将详细说明。另外可参考另一篇文章:https://lobin.iteye.com/blog/2437928
 
HandleArea

jobject

jobject是个JNI句柄,或称为native句柄、本地句柄。在开发native时,经常会用到这个句柄,如果java native方法是个实例(非静态)方法,生成的本机接口函数第2个参数类型就是jobject,用于表示该native方法所对应的java对象的JNI句柄。
在C++中,它被定义为_jobject类型的指针。
class _jobject {};
typedef _jobject *jobject;
但在C语言环境中,它被定义为_jobject类型的指针。
struct _jobject;
typedef struct _jobject *jobject;
JNI句柄可以直接转换为一个oop指针
jobject handle = ...

oop* ptr = (oop*)handle;
 
 
关于jobject可参考另一篇文章:https://lobin.iteye.com/blog/2437928
分享到:
评论

相关推荐

    Java JVM 面试题总结

    - **句柄访问**:每个对象都有一个句柄指向其对象头,对象头中包含实际的数据和元数据。 - **直接指针**:对象头中直接存放对象数据的地址,这种方式减少了指针寻址的开销。 #### 8. 如何判断对象已经死亡? 判断...

    JVM虚拟机面试题汇总

    - **句柄访问**: 通过句柄池中的句柄来访问对象实例数据。 - **直接指针**: 直接通过对象的地址访问对象实例数据。 4. **内存溢出(Out Of Memory Error, OOM)**: - **堆溢出**:对象实例数量超过最大堆容量限制...

    03.Java对象初始化1

    优缺点:句柄引用,当对象实例发生改变的时候,只需要改掉句柄对实例对象物理地址的引用即可,修改比较方便与快捷缺点,但是确定是对象的分配比较频繁,因此获取对象是一个频繁的动作,使用直接指针访问,这样的性能...

    JVM 面试题总结.md

    1. **句柄访问**:在Java堆之外维护一个句柄池,句柄中包含了对象实例数据与类型数据各自具体的内存地址信息。 2. **直接指针**:对象头中包含了对象的实例数据与类型数据的地址信息,这种方式的访问速度更快。 ###...

    JVM底层原理课件PPT

    ### JVM底层原理——类加载子系统详解 #### 一、引言 Java虚拟机(JVM)作为Java程序运行的基础环境,其内部结构复杂且功能强大。本文将基于“JVM底层原理课件PPT”中关于类加载子系统的介绍进行深入解析。类加载子...

    jvm_learn_note.pdf

    - **对象访问定位**:通过栈上的引用访问堆上的对象,有两种方式:句柄访问和直接指针访问。 垃圾收集器是JVM的关键组件,负责自动回收不再使用的内存。它主要通过两种算法来判断对象是否死亡: 1. **引用计数算法...

    对象由生到死的一些过程.doc

    2. **句柄定位**:这种方式维护一个句柄池,对象引用指向句柄池中的地址,句柄池再指向实际对象和类信息。这种方式在GC时只需更改句柄池,但访问速度较慢。 **对象内存布局** 1. **对象头**:包含Mark Word(用于...

    JVM面试专题及答案(1).pdf

    JVM提供了两种主要的访问方式:句柄访问和直接指针访问。 #### 4. 垃圾回收(GC) 垃圾回收是JVM自动管理内存的关键机制之一,主要包括以下几种算法: - **引用计数算法**:通过维护对象的引用计数来判断对象是否...

    JVM常见面试题.docx

    句柄访问通过句柄池访问对象数据,reference稳定;直接指针访问速度快,但reference会随对象移动。 理解以上知识点对于优化Java程序性能、避免内存泄漏和提高应用稳定性具有重要意义。开发者需要深入理解JVM的工作...

    10_对象的实例化内存布局与访问定位.pptx

    - **句柄访问**(HotSpot 默认):在这种模式下,JVM为每个对象分配一个句柄,句柄是一个包含对象实例数据地址和类型数据地址的结构。当程序访问对象时,通过句柄来间接访问,这样做的好处是对象移动时,只需要更新...

    详解JVM的内存对象介绍[创建和访问]

    4. 如果该类已经被加载,则开始给该对象在JVM的堆中分配内存。 5. 虚拟机初始化操作,虚拟机对分配的空间初始化为零值。 6. 执行init方法,初始化对象的属性,至此对象被创建完成。 7. java虚拟机栈中的Reference...

    JVM常用知识(面试可用)

    - **对象访问定位**:句柄和直接指针两种方式,影响内存布局和访问速度。 4. **垃圾收集**: - **判断对象是否已死**:引用计数法和可达性分析算法(GCRoots)。 - **垃圾收集算法**:标记-清除、复制、标记-...

    Java虚拟机(JVM)面试题(2022最新版)-重点

    - **句柄访问:** 每个对象都有一个句柄指向方法区的对象类型数据,另一个指向对象的数据。 - **直接指针:** 直接使用对象头中的地址来定位对象的数据。 #### 内存溢出异常 **内存溢出(Memory Overflow):** 当程序...

    JVM面试专题.pdf

    - **对象访问定位**:通过句柄或直接指针方式找到对象实例。 4. **垃圾收集(GC)判定方法**: - **引用计数法**:简单但无法处理循环引用问题,JVM未采用。 - **可达性分析法(引用链法)**:通过GC Roots进行...

    使用C++创建java虚拟机JVM,使用JNI调用java函数.zip

    这通过`GetMethodID`实现,需要提供类的句柄、方法的签名以及方法名。例如,调用静态方法`public static void myMethod()`,签名应为`(V)`。 3. **调用Java方法**:有了方法ID,就可以使用`CallVoidMethod`, `...

    JVM.pdf

    - 局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等于...,也可能是指向一个代表对象的句柄或者其他与此对象相关的位置)...

    常见的面试题21232.pdf

    以下是对JVM运行时数据区、常见异常、对象创建过程以及对象访问定位等知识点的详细解释: 1. **JVM运行时数据区**: - **程序计数器**:每个线程都有自己的程序计数器,用于记录当前线程正在执行的字节码指令的...

    JVM面试专题及答案.pdf

    对象的内存分配依赖于JVM的内存管理机制,常见的访问定位方式包括使用句柄和直接指针两种。 GC(垃圾回收)是JVM自动管理内存的关键机制,它能自动回收不再使用的对象占用的内存空间。JVM中垃圾回收的判定方法主要...

Global site tag (gtag.js) - Google Analytics