jvm oop-klass对象模型

简介: 因此,当讲到jvm的对象模型的实现时候,可能会很自然地想到,只要java对象底层对应一个C++对象,问题就解决了。因为klassKlass的指针始终是指向自己的。其中_mark,_metadata一起合成为了对象头,里面包含了锁状态标志、线程持有的锁等标志,_metadata包含了两个指针,指向klass,klass包含了实例对象的元数据。上来就是三张图,c++写的,虽然咱们不能完全看明白,但是从定义属性这些大致也有了个了解,这个模型是由oop类和klass组合起来的,然后这两个大类下面又有很多的子类。

jvm对象模型可以从hotspot7的源代码的github上获取到进行学习.
注:本文内容都是以jdk7对应的hotspot虚拟机为基础进行分析的.

一.oop-klass的层级关系
首先,今天讲的东西是java对象在jvm层面的具体映射,它叫做oop-klass模型。咱们先来看看这个模型是怎么组成的。
oopsHierarchy.hpp的源代码,具体可以点进入到官方的github仓库里面看看,我这里放的是我fork的链接。(读者:为啥不直接放官方的链接,我:咱这不是心存私心引一下流量到自己的github嘛,虽然并没有啥内容可看,捂脸哭表情)。
好了废话时间结束,咱们先看看jvm对象模型的层次结构。

引用Hotspot实战里面的一张图,oop各模块的组成:
oop各模块组成

oop层级部分:
oop层级

klass层级部分:
klass层级
上来就是三张图,c++写的,虽然咱们不能完全看明白,但是从定义属性这些大致也有了个了解,这个模型是由oop类和klass组合起来的,然后这两个大类下面又有很多的子类。

二.oop层级部分:
看完了jvm整个模型的构成,我们先来看看oop部分的作用。
参考hotspot源码中的oop.hpp部分.

oop.hpp翻译:
1.oopDesc是对象类的顶层基类。
2.Desc类描述了Java对象的格式,以便可以从C ++访问这些字段。
3.oopDesc是抽象的。(完整的类层次结构见oopHierarchy).
4.oop类不允许虚拟功能.

我们可以将oop的部分理解成java部分的对象,然后klass是给jvm使用的内部对象。
下面是oop各子类继承关系和各个子模块作用。

oop继承关系

oop的用途

不同类型有不同的用处,比如;创建一个Java对象实例的时候,jvm会创建一个instanceOopDesc对象在java层面来表示这个Java对象。如果是创建一个方法的时候,JVM会创建一个methodOopDesc对象来表示这个方法。

oop对象头
所有的子类oop都是继承的oopDesc,我们知道jvm中的对象包含了三部分:对象头,实例数据,对齐填充。
其中_mark,_metadata一起合成为了对象头,里面包含了锁状态标志、线程持有的锁等标志,_metadata包含了两个指针,指向klass,klass包含了实例对象的元数据。

三.klass层级部分
我们知道Hotspot的底层实现使用C++实现的,C++也是一门面向对象的语言。因此,当讲到jvm的对象模型的实现时候,可能会很自然地想到,只要java对象底层对应一个C++对象,问题就解决了。在查看了一下参考资料发现,设计者为了避免每个对象中都有一个C++VTBL指针,采用了将对象模型一分为二的做法:oop-klass模型。看到这里可能会有点懵逼这个C++VTBL指针是干嘛的。这个不是本文重点,先略过。首先,我们这么理解,一个C++对象要实现两部分功能:
1.语言层面的对象;
2.包含虚函数;(可以先简单的理解为实现多态要用的东西).

然后我们看klass源码中的描述
klass.hpp翻译:
Klass是klassoop的一部分,它提供了:
1.语言层面的java类对象(方法字典等)
2.为该对象提供了虚拟机的调度行为
这两个功能完成了一个C++类的功能。顶层的Klass实现第一点,而所有子类提供额外的虚拟功能实现了第二点。
因此,java的oop-klass对象模型中,klass和其子类就实现了C++对象中的这两个功能.
在实现对象模型中出现oop/klass二分法的一个原因是我们不希望每个对象都有一个C++ vtbl指针。因此,正常的oops没有任何虚函数。相反,他们将所有虚函数转发给它们的klass,klass具有一个vtbl并根据对象执行C++调度实际类型。(有关转发代码,请参阅oop.inline.hpp。).所有实现此调度的函数都以“oop_”为前缀!

klass的层级结构:
klass继承

四.klass和oop之间的联系

oop和klass的关系

所有的oop对象实例都会有一个指针,指向对应的instanceKlass,同时instanceKlass也会有一个instanceKlassKlass来描述它。这种链条直到KlassKlass终止。因为klassKlass的指针始终是指向自己的。参考内容

__注__:这里看大家源码的时候可能会有一个疑问,Klass_vtbl的源码中(就是Klass.hpp),没有出现_mark和_metadata,那怎么从instanceKlass指向instanceKlassKlass呢?在JDK8之前(本文章是基于JDK7),方法区内的描述类型的元数据对象,也是由GC管理的。所有由GC统一管理的对象,都要继承自oopDesc,因为oopDesc有_mark和_metadata,所以作为它的子类的Klass都包含了头信息_mark和metadata。从JDK8开始,类型元数据都移出了GC堆,所以Klass这个属性可以直接指向Klass类了。

参考资料:

1.深入理解多线程(二)—— Java的对象模型
2.HotSpotVM 对象机制实现浅析#1
3.借HSDB来探索HotSpot VM的运行时数据

相关文章
|
6月前
|
安全 Java
对 JVM 的类加载机制以及寻找字节码文件的“双亲委派模型”的理解
对 JVM 的类加载机制以及寻找字节码文件的“双亲委派模型”的理解
39 0
|
6月前
|
存储 安全 算法
深入剖析JVM内存管理与对象创建原理
JVM内存管理,JVM运行时区域,直接内存,对象创建原理。
104 2
|
6月前
|
存储 算法 安全
【JVM】深入理解JVM对象内存分配方式
【JVM】深入理解JVM对象内存分配方式
86 0
|
2天前
|
存储 算法 Java
散列表的数据结构以及对象在JVM堆中的存储过程
本文介绍了散列表的基本概念及其在JVM中的应用,详细讲解了散列表的结构、对象存储过程、Hashtable的扩容机制及与HashMap的区别。通过实例和图解,帮助读者理解散列表的工作原理和优化策略。
14 1
散列表的数据结构以及对象在JVM堆中的存储过程
|
24天前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
49 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
2月前
|
安全 Java 应用服务中间件
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
什么是类加载器,类加载器有哪些;什么是双亲委派模型,JVM为什么采用双亲委派机制,打破双亲委派机制;类装载的执行过程
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
|
24天前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
46 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
1月前
|
Java
【JVM】双亲委派模型
【JVM】双亲委派模型
20 1
|
26天前
|
算法 Java
JVM进阶调优系列(3)堆内存的对象什么时候被回收?
堆对象的生命周期是咋样的?什么时候被回收,回收前又如何流转?具体又是被如何回收?今天重点讲对象GC,看完这篇就全都明白了。
|
3月前
|
存储 Java 程序员
Java中对象几种类型的内存分配(JVM对象储存机制)
Java中对象几种类型的内存分配(JVM对象储存机制)
79 5
Java中对象几种类型的内存分配(JVM对象储存机制)