JAVA对象模型

     首次接触到java对象头的时候还是看SYNCHRONIZED关键字的时候,下面的内容也是比较生涩难懂,目前的我做不到完全理解,但我会多去咀嚼,理解。现在我们来好好的看看Java对象模型:

     几乎所有的Java对象保存在堆内存中(有例外,自行了解),在内存中Java对象包含三部分:对象头、实例数据和对齐填充。其中对象头是一个很关键的部分,因为对象头中包含锁状态标志、线程持有的锁等标志。我i们对对象进行操作时,其实操作的是对象的引用。那么对象本身在JVM中的结构如下所示(基于HotSpot虚拟机):

oop-klass model

    HotSpot JVM设计了一个OOP-Klass Model。OOP(Ordinary Object Pointer)指的是普通对象指针,而Klass用来描述对象实例的具体类型。

     为什么HotSpot要设计一套oop-klass model呢?因为HotSpot是基于c++实现,本身是具备面向对象基本特征的,所以Java中的对象表示,最简单的做法是为每个Java类生成一个c++类与之对应,但是:HotSopt JVM的设计者不想让每个对象中都含有一个vtable(虚函数表)。

     关于opp-klass模型的整体定义,在HotSpot的源码中可以找到,被分成两个独立的部分:OOP框架和Klass框架,在oopsHierarchy.hpp里定义了oop和klass各自的体系。

oop-klass结构

                                

oop体系:

                               

     上面列出的是整个Oops模块的组成结构,其中包含多个子模块。每一个子模块对应一个类型,每一个类型的OOP都代表一个在JVM内部使用的特定对象的类型。
     从上面的代码中可以看到,有一个变量opp的类型是oppDesc ,它是OOPS类的共同基类型。在Java程序中每创建一个新的对象在JVM内部就会相应地创建一个对应类型的OOP对象。在HotSpot中,根据JVM内部使用的对象业务类型,生成对应的oopDesc的子类。例如,instanceOopDesc表示类实例。对应的就是当我们使用new创建一个Java对象实例的时候,JVM会创建一个instanceOopDesc对象来表示这个Java对象。

以下是具体的一个关系图:

                         

     在HotSpot中,oopDesc类定义在oop.hpp中,instanceOopDesc定义在instanceOop.hpp中,arrayOopDesc定义在arrayOop.hpp中。

简单看一下相关定义:

                                             

_mark :对象头中有和锁相关的运行时数据,这些运行时数据是synchronized以及其他类型的锁实现的重要基础,而关于锁标记、GC分代等信息均保存在_mark中。

_metadata:前面介绍到的_metadata是一个共用体,其中_klass是普通指针,_compressed_klass是压缩类指针。


klass体系

                                         

                        

Klass向JVM提供两个功能:
               实现语言层面的Java类(在Klass基类中已经实现)
               实现Java对象的分发功能(由Klass的子类提供虚函数实现)

     HotSopt JVM的设计者把对象一拆为二,分为klass和oop,其中oop主要在于表示对象的实例数据,所以其中不含有任何虚函数。而klass为了实现虚函数多态,所以提供了虚函数表。所以,关于Java的多态,其实也有虚函数的影子在。

    _metadata是一个共用体,其中_klass是普通指针,_compressed_klass是压缩类指针。这两个指针都指向instanceKlass对象,它用来描述对象的具体类型。


instanceKlass
    JVM在运行时,需要一种用来 标识Java内部类型的机制---为每一个已加载的Java类创建一个instanceKlass对象,用来在JVM层表示Java类。

来看下instanceKlass的内部结构:

                                                

      在JVM中,对象在内存中的基本存在形式就是oop。那么,对象所属的类,在JVM中也是一种对象,因此它们实际上也会被组织成一种oop,即klassOop。同样的,对于klassOop,也有对应的一个klass来描述,它就是klassKlass,也是klass的一个子类。klassKlass作为oop的klass链的端点。关于对象和数组的klass链大致如下图:(这段很绕,多看几遍)

                               

                        

         一个java对象如何存储在内存里:对象的实例(instantOopDesc)保存在堆上,对象的元数据(instantKlass)保存在方法区,对象的引用保存在栈上。方法区用于存储虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 所谓加载的类信息,就是给每一个被加载的类都创建了一个 instantKlass对象。

总结

     每一个Java类,在被JVM加载的时候,JVM会给这个类创建一个instanceKlass,保存在方法区,用来在JVM层表示该Java类。当我们在Java代码中,使用new创建一个对象的时候,JVM会创建一个instanceOopDesc对象,这个对象中包含了对象头以及实例数据。

      考虑到虚拟机的空间效率,Mark Word被设计成一个非固定的数据结构以便在极小的空间内存储尽量多的信息,它会根据对象的状态复用自己的存储空间。

      下图描述了在32位虚拟机上,在对象不同状态时 mark word各个比特位区间的含义:

          

         对象头中主要包含了GC分代年龄、锁状态标记、哈希码、epoch等信息。从上图中可以看出,对象的状态一共有五种分别是无锁态、轻量级锁、重量级锁、GC标记和偏向锁。在32位的虚拟机中有两个Bits是用来存储锁的标记为的,但是我们都知道,两个bits最多只能表示四种状态:00、01、10、11,那么第五种状态如何表示呢 ,就要额外依赖1Bit的空间,使用0和1来区分。

文章内容主要参考以下连接:

http://www.hollischuang.com/archives/1910 

http://www.hollischuang.com/archives/1953 


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Java对象内存模型包括对象头、实例数据和对齐填充三部分。对象头包含了关于堆对象的布局、类型、GC状态、同步状态和标识哈希码等基本信息。实例数据存放了类的数据信息、父类的信息以及对象字段属性信息。对齐填充主要是为了字节对齐而填充的数据,以凑齐8字节的倍数。 在JVM中,我们可以使用openjdk的jol工具来打印对象信息。通过调用`ClassLayout.parseInstance(object).toPrintable()`方法,我们可以打印出对象的信息。 例如,对于一个无属性的对象,打印的信息如下: ``` java.lang.Object object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243) 12 4 (loss due to the next object alignment) Instance size: 16 bytes Space losses: 0 bytes internal + 4 bytes external = 4 bytes total ``` 这段信息描述了对象的各个部分。例如,对象头占据了前12个字节,分为三部分,每部分占4个字节。实例数据为空,所以没有具体的值。 这就是Java对象的内存模型。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Java对象内存模型](https://blog.csdn.net/u013190417/article/details/122532408)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值