目录

jvm中OOP-KLASS模型

基本介绍

在JVM中,使用了OOP-KLASS模型来表示java对象,这里的 oop 指的是 普通对象指针 (普通对象指针),它表示对象的实例信息,看起来像个指针实际上是藏在指针里的对象。而klass 则包含元数据和方法信息 ,用来描述Java类。

模型设计初衷

那么为何要设计这样一个一分为二的对象模型呢?这是因为HotSopt JVM的设计者不想让每个对象中都包含一个vtable(虚函数表),所以就把对象模型拆成klass和oop,其中oop中不包含任何虚函数,而klass就包含虚函数表,可以进行方法调度。这个模型其实是 参照的Strongtalk VM的对象模型。

klass

一个Klass对象代表一个类的元数据。它提供:

1
2
language level class object (method dictionary etc.)
provide vm dispatch behavior for the object

所有的函数都被整合到一个C++类中。  

Klass对象的继承关系: xxxKlass <:< Klass <:< Metadata <:< MetaspaceObj

可以说Klass就是类在JVM中的数据结构

OOP

oop 类型其实是 oopDesc* 。在Java程序运行的过程中,每创建一个新的对象,在JVM内部就会相应地创建一个对应类型的oop对象。各种oop类的共同基类为 oopDesc 类。JVM内部,一个Java对象在内存中的布局可以连续分成两部分: instanceOopDesc 和实例数据。 instanceOopDesc 和 arrayOopDesc 又称为对象头。instanceOopDesc 对象头包含两部分信息: Mark Word 和 元数据指针 ( Klass* ):

Mark Word :instanceOopDesc中的 _mark 成员。它用于存储对象的运行时记录信息,如哈希值、GC分代年龄(Age)、锁状态标志(偏向锁、轻量级锁、重量级锁)、线程持有的锁、偏向线程ID、偏向时间戳等。Mark Word允许压缩。   

元数据指针 :instanceOopDesc中的 _metadata 成员,它是联合体,可以表示未压缩的Klass指针( _klass )和压缩的Klass指针。对应的klass指针指向一个存储类的元数据的Klass对象

可以说,instanceOopDesc就是普通对象的对象头,其中有一个指针指向了它所属的Klass,也就是类结构。

JVM在加载一个类时,会在方法区创建该类的Klass对象,并同时生成一个属于该Klass对象的java.lang.class对象放于堆中,也就是java.lang.class的instanceOopDesc。当我们访问类的元数据时,是通过java.lang.class的instanceOopDesc来访问的,java.lang.class的instanceOopDesc中包含了访问该类Klass对象的属性、方法、注解等元数据的方法。

它们的指向是这样的:类A的instanceOopDesc —-> 类A的Klass —–> 类A的java.lang.class的instanceOopDesc。

也就是说Klass代表的类的元数据是不会直接暴露给对象进行访问的,而是通过Klass的java.lang.class对象来进行间接的访问。这样做可以规范外部对Klass访问的行为,防止对元数据造成破坏。

Klass持有一个指向对应java.lang.class对象的引用,叫做_java_mirro,java.lang.class对象被设计为类的元数据的一面镜子,这也是反射机制命名的原因。

参考 从Oop-Klass模型看透反射