JVM OOP-Klass二分模型

1 概述

HotSpot是基于c++实现,而c++是一门面向对象的语言,本身具备面向对象基本特征,所以Java中的对象表示,最简单的做法是为每个Java类生成一个c++类与之对应。

但HotSpot JVM并没有这么做,而是设计了一个OOP-Klass Model。这里的 OOP 指的是 Ordinary Object Pointer (普通对象指针),它用来表示对象的实例信息,看起来像个指针实际上是藏在指针里的对象。而 Klass 则包含元数,用来描述Java类。

之所以采用这个模型是因为HotSopt JVM的设计者不想让每个对象中都含有一个vtable(虚函数表),所以就把对象模型拆成klass和oop,其中oop中不含有任何虚函数,而Klass就含有虚函数表,可以进行method dispatch(方法调度)。

OOP(Ordinary Object Pointer)所指向的是堆中的对象
对象的Klass指针指向instanceKlass,instanceKlass是类的元数据,在元空间中

instanceKlass中的_java_mirror指针指向堆中的Class对象(即类的Java镜像)

在这里插入图片描述

2 OOP-Klass模型

2.1 Klass

Klass简单的说是Java类在HotSpot中的c++对等体,用来描述Java类。

  • Klass主要有两个功能:
    • 实现语言层面的Java类
    • 实现Java对象的分发功能

那Klass是什么时候创建的呢?一般jvm在加载class文件时,会在方法区创建instanceKlass,表示其元数据,包括常量池、字段、方法等。


(1)instanceKlass其实是Klass的一个对象,表示类的元数据Klass定义的结构如下:
在这里插入图片描述

  • _layout_helper:描述对象整体布局
  • _name:表示类名
  • _java_mirror:表示Klass的Java层镜像类(指向堆中的Class对象,表示类的Java镜像
  • _super:表示父类
  • _subklass:表示第一个子类
  • next_slibling:指向的是下一个兄弟节点,JVM通过_subklass->next_slibling可以找到下一个子类
    (2)instanceKlass实例信息的结构如下(即为instanceKlass就是用来描述类,即为类的元数据):
    在这里插入图片描述
    (3)从JDK 1.3到JDK 6的HotSpot VM,静态变量保存在类的元数据(InstanceKlass)的末尾。而从JDK 7开始的HotSpot VM,静态变量则是保存在类的Java镜像(java.lang.Class实例)的末尾。在HotSpot VM中,对象、类的元数据(InstanceKlass)、类的Java镜像,三者之间的关系是这样的:
    在这里插入图片描述
    即InstanceKlass中的_java_mirror指针指向了堆中Class对象(类的java镜像)。每个Java对象的对象头里,_klass字段会指向一个VM内部用来记录类的元数据用的InstanceKlass对象;InsanceKlass里有个_java_mirror字段,指向该类所对应的Java镜像----java.lang.Class实例。HotSpot VM会给Class对象注入一个隐藏字段“klass”,用于指回到其对应的InstanceKlass对象。这样,klass与mirror之间就有双向引用,可以来回导航。这个模型里,java.lang.Class实例并不负责记录真正的类元数据,而只是对VM内部的InstanceKlass对象的一个包装供Java的反射访问用。
2.2 OOP

Klass是在class文件在加载过程中创建的,OOP则是在Java程序运行过程中new对象时创建的。

一个OOP对象包含以下几个部分:

  • instanceOopDesc,也叫对象头
    • Mark Word,主要存储对象运行时记录信息,如hashcode, GC分代年龄,锁状态标志,线程ID,时间戳等
    • 元数据指针,即指向方法区的instanceKlass实例
  • 实例数据
  • 对齐的字节(整个对象必须8字节对齐)
    注:
    (1)instanceOopDesc(对象头)其实是OopDesc的实例,OopDesc的结构如下:
    在这里插入图片描述oopDesc中包含两个数据成员:_mark 和 _metadata。其中markOop类型的_mark对象表示的是前面讲到的Mark World。_metadata是一个共用体,其中_klass是普通指针,_compressed_klass是压缩类指针,它们就是前面讲到的元数据指针,这两个指针都指向instanceKlass对象,它用来描述对象的具体类型。

3 实例说明

假如我们有如下代码:

class Model
{
    public static int a = 1;
    public int b;

    public Model(int b) {
        this.b = b;
    }
}

public static void main(String[] args) {
    int c = 10;
    Model modelA = new Model(2);
    Model modelB = new Model(3);
}

上述代码得OOP-Klass模型入下所示:
在这里插入图片描述

总结

当我们执行new Object()的时候,首先JVM native层判断该类是否被加载过,没有的话就进行类的加载,并在JVM内部创建一个instanceKlass对象表示该类的运行时元数据(Java层的Class对象),到初始化的时候,JVM就创建一个instanceOopDesc对象(对象头)表示该对象的实例,然后进行Mark Word信息填充,将元数据指针指向Klass对象,并填充实例变量。

部分转载自: http://blog.csdn.net/linxdcn/article/details/72850375.
推荐阅读: https://www.zhihu.com/question/50258991. RednaxelaFX
大佬

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值