JVM-oop-klass模型

JAVA运行时环境逻辑图

在这里插入图片描述

一、oop-klass模型

oop-klass模型是JVM底层的数据结构,理解JVM的必要概念

• Klass表示Java类在JVM中的存在形式
    • InstanceKlass表示类的元信息
		• InstanceMirrorKlass表示类的Class对象
		• InstanceRefKlass表示?
	• ArrayKlass表示数组类的元信息
		• TypeArrayKlass表示基本数组类的元信息
		• ObjArrayKlass表示引用数组类的元信息
• oopDesc表示JAVA对象在JVM中的存在形式
	• instanceOopDesc表示普通类对象(非数组类对象)
	• arrayOopDesc表示数组类对象
		• typeArrayOopDesc表示基本数组类对象
		• objArrayOopDesc表示引用数组类对象

下面是这几个Klass的继承关系图
在这里插入图片描述

下面是这几个oop的继承关系图
在这里插入图片描述

1. InstanceKlass

class InstanceKlass: public Klass {
friend class VMStructs;
friend class ClassFileParser;
friend class CompileReplay;
protected:
// Constructor
InstanceKlass(int vtable_len,
int itable_len,
int static_field_size,
int nonstatic_oop_map_size,
ReferenceType rt,
AccessFlags access_flags,
bool is_anonymous);
...
protected:
// Annotations for this class
Annotations*    _annotations;
Klass*          _array_klasses;
ConstantPool* _constants;Array* inner_classes;
char*           _source_debug_extension;
Symbol*         _array_name;
int             _nonstatic_field_size;
int             _static_field_size;    // number words used by static fields (oop and non-oop) in this klass
u2              _generic_signature_index;
u2              _source_file_name_index;
u2              _static_oop_field_count;// number of static oop fields in this klass
u2              _java_fields_count;    // The number of declared Java fields
int             _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks
bool            _is_marked_dependent;  // used for marking during flushing and deoptimization
bool            _has_unloaded_dependent;
enum {
_misc_rewritten                = 1 << 0, // methods rewritten.
_misc_has_nonstatic_fields     = 1 << 1, // for sizing with UseCompressedOops
_misc_should_verify_class      = 1 << 2, // allow caching of preverification
misc_is_anonymous             = 1 << 3, // has embedded host_klass field
misc_is_contended             = 1 << 4, // marked with contended annotation
misc_has_default_methods      = 1 << 5, // class/superclass/implemented interfaces has default methods
misc_declares_default_methods = 1 << 6  // directly declares default methods (any access)
};
u2              misc_flags;
u2              minor_version;        // minor version number of class file
u2              major_version;        // major version number of class file
Thread*         init_thread;          // Pointer to current thread doing initialization (to handle recusive initialization)
int             vtable_len;           // length of Java vtable (in words)
int             itable_len;           // length of Java itable (in words)
OopMapCache*    volatile oop_map_cache;   // OopMapCache for all methods in the klass (allocated lazily)
MemberNameTable* member_names;        // Member names
JNIid*          jni_ids;              // First JNI identifier for static fields in this class
jmethodID*      methods_jmethod_ids;  // jmethodIDs corresponding to method_idnum, or NULL if none
nmethodBucket*  dependencies;         // list of dependent nmethods
nmethod*        osr_nmethods_head;    // Head of list of on-stack replacement nmethods for this class
BreakpointInfo* breakpoints;          // bpt lists, managed by Method*
GrowableArray<PreviousVersionNode > previous_versions;
JvmtiCachedClassFileData* cached_class_file;
volatile u2     _idnum_allocated_count;         change
u1              _init_state;                    // state of class
u1              _reference_type;                // reference type
JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map;  // JVMTI: used during heap iteration
NOT_PRODUCT(int _verify_count;)  // to avoid redundant verifies
Array<Method> _methods;
Array<Method> _default_methods;
Array<Klass> _local_interfaces;
Array<Klass> transitive_interfaces;
Array*     method_ordering;Array*     default_vtable_indices;
Array*      _fields;

这里贴一下这些成员变量的中文解释
_annotations:保存该类的所有注解
_array_klasses:保存数组元素所关联的klass指针
_constants:保存该类的常量池指针
_inner_classes:保存内部类相关的信息
_array_name:如果该类是数组,就会生成数组类名词,如“[Ljava/lang/String;”
_nonstatic_field_size:非静态字段数量
_static_field_size:静态字段数量
_generic_signature_index:泛型签名在常量池中的索引
_source_file_name_index:文件名在常量池中的索引
_static_oop_field_count:该类包含的静态的引用类型字段个数
_java_fields_count:已声明的Java字段数量
_nonstatic_oop_map_size:非静态oop映射块的大小(以字为单位)
_is_marked_dependent:用于刷新和反优化期间打标
_minor_version:主版本号
_major_version:次版本号
_init_thread:初始化此类的线程
_vtable_len:虚函数表的大小
_itable_len:接口函数表的大小
_oop_map_cache:该类所有方法的OopMapCache(延迟分配)
_member_names:MemberNameTable指针
_jni_ids:存放jni_id单向链表的首地址(什么是jni_id?)
_methods_jmethod_ids:与method_idnum对应的jmethodIDs,如果没有,则为NULL
_dependencies:存放nmethod的Bucket的首地址
_osr_nmethods_head:栈上替换nmethods的链表的首地址
_breakpoints:断点链表首地址
_previous_versions:此实例的前一个版本的有趣部分的数组。请参见下面的PreviousVersionWalker
_cached_class_file:缓存的类文件
_idnum_allocated_count:已经分配的idnum的个数
_init_state:该类的状态,值:allocated(已分配内存但未链接)、loaded(加载并插入到类层次结构中但仍未链接)、linked(验证及链接成功但未初始化)、being_initialized(正在初始化)、fully_initialized(已完成初始化)、initialization_error(初始化出错)
_reference_type:引用类型
_methods:存储该类的所有方法对象的指针的数组指针
_default_methods:存储从接口继承的所有方法对象的指针的数组指针
_local_interfaces:数组指针,存储所有实现的接口的指针
_transitive_interfaces:数组,存储直接实现的接口指针+接口间继承实现的接口指针
_method_ordering:包含类文件中方法的原始顺序的Int数组,JVMTI需要用到
_default_vtable_indices:默认构造方法在虚表中的索引
_fields:类的成员属性

2. InstanceMirrorKlass

class InstanceMirrorKlass: public InstanceKlass {
  friend class VMStructs;
  friend class InstanceKlass;
 private:
  static int _offset_of_static_fields;
  // Constructor
  InstanceMirrorKlass(int vtable_len, int itable_len, int static_field_size, int nonstatic_oop_map_size, ReferenceType rt, AccessFlags access_flags,  bool is_anonymous)
    : InstanceKlass(vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt, access_flags, is_anonymous) {}
 public:
  InstanceMirrorKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
  // Type testing
  bool oop_is_instanceMirror() const             { return true; }

3. InstanceKlass和InstanceMirrorKlass

InstanceKlass和InstanceMirrorKlass
可以看出来
• InstanceKlass中定义了Java运行时环境类所需的所有数据信息,比如 constants 常量池、methods 方法 等(An InstanceKlass is the VM level representation of a Java class. It contains all information needed for at class at execution runtime.)
• InstanceMirrorKlass是InstanceKlass的一个子类
• InstanceMirrorKlass是java.lang.Class类专用的InstanceKlass(An InstanceMirrorKlass is a specialized InstanceKlass for java.lang.Class instances.)
简单总结一下,InstanceKlass包含了Java运行时环境中类所需的所有数据信息,在类加载这一步,类加载器会将.class文件读入类加载器的class content,然后以InstanceKlass的形式写入JVM内存区域的方法区中,而InstanceMirrorKlass是类所对应的Class对象(java.lang.Class)的InstanceKlass
对于InstanceKlass,在Java中,对于所有类,类的内部属性轮廓是不是可以认为是一样的?类都有父类、实现接口、变量、方法、代码块等,而变量和方法也有属性,即可访问性(public、private、protected、default)、静态与非静态,还有数组形式的。无论如何,类的内部属性以及属性的属性,是有限的、可列举的,那么在JVM中以C++代码就可以用一个类来表示,它就是InstanceKlass,这一层是比较好理解的

对于InstanceMirrorKlass的理解,首先需要理解什么是java.lang.Class,我们来看一下这个类的注释吧:Instances
of the class Class represent classes and interfaces in a running Java
application.
翻译过来说,就是类或接口在Java运行时环境中的一个表达方式,再看看java.lang.Class的方法就知道,getConstructors()、getMethods()、getFields()、getDeclaredFields(),这些都是类的内部属性,且对于任何类来说,都可以用形如A.class的方法来获取java.lang.Class,即每个Java类都有一个java.lang.Class,那么在JVM中以C++代码表示,每个类的java.lang.Class就是InstanceMirrorKlass。java.lang.Class也是一个类,InstanceMirrorKlass是InstanceKlass的子类

关于Class对象,JVM并没有将描述Java类元信息的instanceKlass直接暴露给Java程序使用,而是又抽象了一层,即所谓的镜像类:instanceMirrorKlass。jdk8以后,类的静态属性也由存储在instanceKlass实例中转为存放
来看一下parseClassFile方法

instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
                                                    ClassLoaderData* loader_data,
                                                   Handle protection_domain,
                                                    KlassHandle host_klass,
                                                    GrowableArray<Handle>* cp_patches,
                                                    TempNewSymbol& parsed_name,
                                                   bool verify,
                                                    TRAPS) {
……
   // Allocate mirror and initialize static fields
   java_lang_Class::create_mirror(this_klass, protection_domain, CHECK_(nullHandle));
……  

来看一下create_mirror方法,第六行代码:初始化静态字段do_local_static_fields

oop java_lang_Class::create_mirror(KlassHandle k, Handle protection_domain, TRAPS) {
……
   Handle mirror = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK_0);
……
     // Initialize static fields
     InstanceKlass::cast(k())->do_local_static_fields(&initialize_static_field, CHECK_NULL);
……

来看一下allocate_instance方法,从代码中可以看出来,是从堆区分配内存的(CollectedHeap::Class_obj_allocate),所以说Class对象是分配在堆上的

instanceOop InstanceMirrorKlass::allocate_instance(KlassHandle k, TRAPS) {
 // Query before forming handle.
 int size = instance_size(k);
  KlassHandle h_k(THREAD, this);
  instanceOop i = (instanceOop) CollectedHeap::Class_obj_allocate(h_k, size, k, CHECK_NULL);
 return i;
}

总结一下,类加载器将.class文件载入JVM中,parse后生成的是instanceKlass对象,之后会生成这个Klass类对应的镜像类实例,并将Java类中的静态变量初始化后存储在镜像类实例中,这个镜像类就是Java代码中的Class对象

4. InstanceRefKlass

描述java.lang.ref.Reference的子类,这部分的概念与强软弱虚引用、垃圾回收有关系

5. ArrayKlass

在理解了InstanceKlass后,这三个类就很好理解了
• ArrayKlass表示的是数组类的元信息(ArrayKlass is the abstract baseclass for all array classes)
• TypeArrayKlass表示基本数组类的元信息(A TypeArrayKlass is the klass of a typeArray, It contains the type and size of the elements)
• ObjArrayKlass表示引用数组类的元信息(ObjArrayKlass is the klass for objArrays)

class ArrayKlass: public Klass {
 friend class VMStructs;
private:
 int      _dimension;         // This is n'th-dimensional array.
  Klass* volatile _higher_dimension;  // Refers the (n+1)'th-dimensional array (if present).
  Klass* volatile _lower_dimension;   // Refers the (n-1)'th-dimensional array (if present).
 int      _vtable_len;        // size of vtable for this klass
  oop      _component_mirror;  // component type, as a java/lang/Cl
TypeArrayKlass
class TypeArrayKlass : public ArrayKlass {
 friend class VMStructs;
private:
  jint _max_length;            // maximum number of elements allowed in an array
 // Constructor
 TypeArrayKlass(BasicType type, Symbol* name);
 static TypeArrayKlass* allocate(ClassLoaderData* loader_data, BasicType type, Symbol* name, TRAPS);
public:
 TypeArrayKlass() {} // For dummy objects.
ObjArrayKlass
class ObjArrayKlass : public ArrayKlass {
 friend class VMStructs;
private:
  Klass* _element_klass;            // The klass of the elements of this array type
  Klass* _bottom_klass;             // The one-dimensional type (InstanceKlass or TypeArrayKlass)
 // Constructor
 ObjArrayKlass(int n, KlassHandle element_klass, Symbol* name);
 static ObjArrayKlass* allocate(ClassLoaderData* loader_data, int n, KlassHandle klass_handle, Symbol* name, TRAPS);
public:
 // For dummy objects
 ObjArrayKlass() {}
6. oopDesc
oopDesc表示JAVA对象在JVM中的存在形式
class oopDesc {
 friend class VMStructs;
private:
 volatile markOop  _mark;
 union _metadata {
    Klass*      _klass;
    narrowKlass _compressed_klass;
  } _metadata;
 // Fast access to barrier set.  Must be initialized.
 static BarrierSet* _bs;
public:
  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);
 void init_mark();
  Klass* klass() const;
  Klass* klass_or_null() const volatile;
  Klass** klass_addr();
  narrowKlass* compressed_klass_addr();
 void set_klass(Klass* 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);
  oop list_ptr_from_klass();
 // size of object header, aligned to platform wordSize
 static int header_size()          { return sizeof(oopDesc)/HeapWordSize; }
 // Returns whether this is an instance of k or an instance of a subclass of k
 bool is_a(Klass* 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);
 // type test operations (inlined in oop.inline.h)
 bool is_instance()            const;
 bool is_instanceMirror()      const;
 bool is_instanceClassLoader() const;
 bool is_instanceRef()         const;
 bool is_array()               const;
 bool is_objArray()            const;
 bool is_typeArray()           const;
...
instanceOopDesc
instanceOopDesc表示普通类对象(非数组类对象)
class instanceOopDesc : public oopDesc {
public:
 // aligned header size.
 static int header_size() { return sizeof(instanceOopDesc)/HeapWordSize; }
 // If compressed, the offset of the fields of the instance may not be aligned.
 static int base_offset_in_bytes() {
   // offset computation code breaks if UseCompressedClassPointers
   // only is true
   return (UseCompressedOops && UseCompressedClassPointers) ?
            klass_gap_offset_in_bytes() :
            sizeof(instanceOopDesc);
  }
 static bool contains_field_offset(int offset, int nonstatic_field_size) {
   int base_in_bytes = base_offset_in_bytes();
   return (offset >= base_in_bytes &&
            (offset-base_in_bytes) < nonstatic_field_size * heapOopSize);
  }
};

arrayOopDesc

arrayOopDesc表示数组类对象

class objArrayOopDesc : public arrayOopDesc {
 friend class ObjArrayKlass;
 friend class Runtime1;
 friend class psPromotionManager;
 friend class CSetMarkOopClosure;
 friend class G1ParScanPartialArrayClosure;
 template <class T> T* obj_at_addr(int index) const {
   assert(is_within_bounds(index), "index out of bounds");
   return &((T*)base())[index];
  }
private:
 // Give size of objArrayOop in HeapWords minus the header
 static int array_size(int length) {
   const uint OopsPerHeapWord = HeapWordSize/heapOopSize;
   assert(OopsPerHeapWord >= 1 && (HeapWordSize % heapOopSize == 0),
          "Else the following (new) computation would be in error");
   uint res = ((uint)length + OopsPerHeapWord - 1)/OopsPerHeapWord;
#ifdef ASSERT
   // The old code is left in for sanity-checking; it'll
   // go away pretty soon. XXX
   // Without UseCompressedOops, this is simply:
   // oop->length() * HeapWordsPerOop;
   // With narrowOops, HeapWordsPerOop is 1/2 or equal 0 as an integer.
   // The oop elements are aligned up to wordSize
   const uint HeapWordsPerOop = heapOopSize/HeapWordSize;
   uint old_res;
   if (HeapWordsPerOop > 0) {
      old_res = length * HeapWordsPerOop;
    } else {
      old_res = align_size_up((uint)length, OopsPerHeapWord)/OopsPerHeapWord;
    }
   assert(res == old_res, "Inconsistency between old and new.");
#endif  // ASSERT
   return res;
  }

typeArrayOopDesc

typeArrayOopDesc表示基本数组类对象

class typeArrayOopDesc : public arrayOopDesc {
protected:
  jchar*    char_base()   const { return (jchar*)   base(T_CHAR); }
  jboolean* bool_base()   const { return (jboolean*)base(T_BOOLEAN); }
  jbyte*    byte_base()   const { return (jbyte*)   base(T_BYTE); }
  jint*     int_base()    const { return (jint*)    base(T_INT); }
  jlong*    long_base()   const { return (jlong*)   base(T_LONG); }
  jshort*   short_base()  const { return (jshort*)  base(T_SHORT); }
  jfloat*   float_base()  const { return (jfloat*)  base(T_FLOAT); }
  jdouble*  double_base() const { return (jdouble*) base(T_DOUBLE); }
 friend class TypeArrayKlass;
public:
  jbyte* byte_at_addr(int which) const {
   assert(is_within_bounds(which), "index out of bounds");
   return &byte_base()[which];
  }
  jboolean* bool_at_addr(int which) const {
   assert(is_within_bounds(which), "index out of bounds");
   return &bool_base()[which];
  }

objArrayOopDesc

objArrayOopDesc表示引用数组类对象

class arrayOopDesc : public oopDesc {
 friend class VMStructs;
 // Interpreter/Compiler offsets
 // Header size computation.
 // The header is considered the oop part of this type plus the length.
 // Returns the aligned header_size_in_bytes.  This is not equivalent to
 // sizeof(arrayOopDesc) which should not appear in the code.
 static int header_size_in_bytes() {
   size_t hs = align_size_up(length_offset_in_bytes() + sizeof(int),
                              HeapWordSize);
#ifdef ASSERT
   // make sure it isn't called before UseCompressedOops is initialized.
   static size_t arrayoopdesc_hs = 0;
   if (arrayoopdesc_hs == 0) arrayoopdesc_hs = hs;
   assert(arrayoopdesc_hs == hs, "header size can't change");
#endif // ASSERT
   return (int)hs;
  }
public:
 // The _length field is not declared in C++.  It is allocated after the
 // declared nonstatic fields in arrayOopDesc if not compressed, otherwise
 // it occupies the second half of the _klass field in oopDesc.
 static int length_offset_in_bytes() {
   return UseCompressedClassPointers ? klass_gap_offset_in_bytes() :
                              sizeof(arrayOopDesc);
  }
  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值