HotSpot虚拟机实现中几个重要的类

时间:2022-03-10 10:30:40

基于:openjdk-8-src-b132-03_mar_2014

HotSpot JVM没有将Java对象直接通过虚拟机映射到C++对象,而是设计了一个Oop/Klass 模型,其中oop为Ordinary Object Pointer,用来表示对象的实例信息;klass用来表示对象元数据信息。

为什么要设计oop/klass这种二分模型的实现?
一个原因是不想让每个对象都包含vtbl(虚方法表),其中oop中不含有任何虚函数,虚表只保存于klass中,可以进行method dispatch。

typedef juint narrowKlass;
typedef juint narrowOop;
typedef class markOopDesc* markOop;
typedef class oopDesc* oop;
typedef class instanceOopDesc* instanceOop;

markOop为指向markOopDesc(对象头)的指针

oop为指向oopDesc的指针

class instanceOopDesc : public oopDesc {}

instanceOop为指向instanceOopDesc(java中Class的实例)的指针

class oopDesc {
friend class VMStructs;
private:
volatile markOop _mark;
union _metadata {
Klass* _klass;
narrowKlass _compressed_klass;
} _metadata;

oopDesc对象包含两部分数据:_mark 和 _metadata;
1、_mark是markOop类型对象,用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等。
2、_metadata是一个联合体,_klass为指向InstanceKlass对象的指针;_compressed_klass是一个压缩指针。在联合体中,各成员共享一段内存空间,一个联合变量的长度等于各成员中最长的长度。
3、_klass字段建立了oop对象与klass对象之间的联系;
1与2构成了Java对象的对象头。

VMStructs:This class is a friend of most classes, to be able to access private fields.

// An InstanceKlass is the VM level representation of a Java class.
// It contains all information needed for at class at execution runtime.


// InstanceKlass layout:

// [C++ vtbl pointer ] Klass

// [subtype cache ] Klass

// [instance size ] Klass

// [java mirror ] Klass

// [super ] Klass

// [access_flags ] Klass

// [name ] Klass

// [first subklass ] Klass

// [next sibling ] Klass

// [array klasses ]

// [methods ]

// [local interfaces ]

// [transitive interfaces ]

// [fields ]

// [constants ]

// [class loader ]

// [source file name ]

// [inner classes ]

// [static field size ]

// [nonstatic field size ]

// [static oop fields size ]

// [nonstatic oop maps size ]

// [has finalize method ]

// [deoptimization mark bit ]

// [initialization state ]

// [initializing thread ]

// [Java vtable length ]

// [oop map cache (stack maps) ]

// [EMBEDDED Java vtable ] size in words = vtable_len

// [EMBEDDED nonstatic oop-map blocks] size in words = nonstatic_oop_map_size

// The embedded nonstatic oop-map blocks are short pairs (offset, length)

// indicating where oops are located in instances of this klass.

// [EMBEDDED implementor of the interface] only exist for interface

// [EMBEDDED host klass ] only exist for an anonymous class (JSR 292 enabled)

HotSpot VM里,Klass用于描述能被GC的对象的类型信息的元数据对象。而Oop则用来描述能被GC的Java对象。
当在Java中new一个对象时,本质是在堆内存创建一个instanceOopDesc对象。instanceOopDesc对象通过元数据指针(_klass或者_compressed_klass)指向方法区的元数据类型的信息。

HotSpot虚拟机实现中几个重要的类

HotSpot虚拟机实现中几个重要的类

JVM可以通过对象引用准确定位到Java堆区中的instanceOopDesc对象,这样既可成功访问到对象的实例信息,当需要访问目标对象的具体类型时,JVM则会通过存储在instanceOopDesc中的元数据指针定位到存储在方法区中的instanceKlass对象上。

方法区是JVM的规范,不同虚拟机有不同的实现方式,我们常说的HotSpot虚拟机,它1.7版本实现方式就是永久代(PermGen),1.8版本是元空间(Metaspace)。

PermGen 是在 JVM 内存区内(not Heap),受到 JVM 内存限制制约。Metaspace 属于原生内存在 JVM 之外,基本上机器有多少内存就可以多大。

JVM 中,InstanceKlass、java.lang.Class的关系?
An InstanceKlass is the VM level representation of a Java class. It contains all information needed for at class at execution runtime. ClassFileParser将class文件在runtime解析成一个个InstanceKlass对象,这个对象是静态字节码文件在运行时Metaspace空间的一个映射。我们知道Java是一种支持反射的语言,为了能在Java层实现对定义类型的解构,JVM实现了InstanceKlass的一个java mirror的概念——java.lang.Class对象。
InstanceKlass类继承自Klass类,在Klass类中有一个成员变量,并且提供了相应的Setter/Getter函数实现:

// java/lang/Class instance mirroring this class
oop _java_mirror;
oop java_mirror() const { return _java_mirror; }
void set_java_mirror(oop m) { klass_oop_store(&_java_mirror, m); }

在java_lang_Class类中,也提供了Class对象与Klass对象的转化函数:

static Klass* as_Klass(oop java_class);
static void set_klass(oop java_class, Klass* klass);

Class类所提供的反射机制,最终都是通过JNI接口,调用相应的native方法,然后通过as_Klass函数转换成InstanceKlass对象,拿到定义类型的元数据信息的。

参考:
http://gao-xianglong.iteye.com/blog/2152345

https://www.jianshu.com/p/252e27863822