文章目录

  • Pre
  • 总览
  • 对象头剖析
    • 查看对象内存的占用情况
  • 对象头C++源码 注释

Pre

JVM - 写了这么多年代码,你知不道new对象背后的逻辑? 中大体介绍了Java中 new 对象背后的主要流程,其中对象头的部分,我们仅仅是点到为止,这里我们深入剖一下Object Header的奥秘 。


总览

初始化默认值以后,JVM要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象的对象头Object Header之中。 这部分数据的长度在32位和64位的虚拟机中分别为32个和64个bits,官方称它为“Mark Word”。

在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、 实例数据(Instance Data)和和对齐填充(Padding) 。

HotSpot虚拟机的对象头包括两部分信息

  • 第一部分用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时 间戳等。

我们以32位操作系统的组成来看一下,下面这个图也是从网上找的,感觉很清晰

  • 对象头的另外一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。

如下红色框框中的示意图


对象头剖析


查看对象内存的占用情况

推荐openjdk的jol工具, 可以查看对象内存的占用情况。

添加依赖

<dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.10</version
</dependency>

示例


import org.openjdk.jol.info.ClassLayout;/*** @author 小工匠* @version v1.0* @create 2020-06-25 16:21* @motto show me the code ,change the word* @blog https://artisan.blog.csdn.net/* @description**/public class ObjectHeaderTest {public static void main(String[] args) {ClassLayout layout = ClassLayout.parseInstance(new Object());System.out.println(layout.toPrintable());System.out.println();ClassLayout layout1 = ClassLayout.parseInstance(new int[]{});System.out.println(layout1.toPrintable());System.out.println();ClassLayout layout2 = ClassLayout.parseInstance(new ArtisanTest());System.out.println(layout2.toPrintable());}// -XX:+UseCompressedOops           默认开启的压缩所有指针// -XX:+UseCompressedClassPointers  默认开启的压缩对象头里的类型指针Klass Pointer// Oops : Ordinary Object Pointerspublic static class ArtisanTest {//8B mark word//4B Klass Pointer   如果关闭压缩-XX:-UseCompressedClassPointers或-XX:-UseCompressedOops,则占用8Bint id;        //4BString name;   //4B  如果关闭压缩-XX:-UseCompressedOops,则占用8Bbyte b;        //1BObject o;      //4B  如果关闭压缩-XX:-UseCompressedOops,则占用8B}
}

【输出结果 】

java.lang.Object object internals:OFFSET  SIZE   TYPE DESCRIPTION                               VALUE0     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[I object internals:OFFSET  SIZE   TYPE DESCRIPTION                               VALUE0     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)                           6d 01 00 f8 (01101101 00000001 00000000 11111000) (-134217363)12     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)16     0    int [I.<elements>                             N/A
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes totalcom.gof.test.ObjectHeaderTest$ArtisanTest object internals:OFFSET  SIZE               TYPE DESCRIPTION                               VALUE0     4                    (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)8     4                    (object header)                           63 cc 00 f8 (01100011 11001100 00000000 11111000) (-134165405)12     4                int ArtisanTest.id                            016     1               byte ArtisanTest.b                             017     3                    (alignment/padding gap)                  20     4   java.lang.String ArtisanTest.name                          null24     4   java.lang.Object ArtisanTest.o                             null28     4                    (loss due to the next object alignment)
Instance size: 32 bytes
Space losses: 3 bytes internal + 4 bytes external = 7 bytes totalProcess finished with exit code 0

【结果说明】

3中类型 : new Object() | new int[]{}数组 | new ArtisanTest()

我这个电脑是64位的操作系统,所以 mark word 占 8个字节。JDK8 klass point 默认开启了指针压缩,所以是4个字节 , 不足8的倍数的,使用padding对齐填充,其目的是为了计算机高效寻址。

最后一个,对于包含多个变量的对象的对象头


对象头C++源码 注释

Bit‐format of an object header (most significant first, big endian layout below):
//
// 32 bits:
// ‐‐‐‐‐‐‐‐
// hash:25 ‐‐‐‐‐‐‐‐‐‐‐‐>| age:4 biased_lock:1 lock:2 (normal object)
// JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object)
// size:32 ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐>| (CMS free block)
// PromotedObject*:29 ‐‐‐‐‐‐‐‐‐‐>| promo_bits:3 ‐‐‐‐‐>| (CMS promoted object)
//
// 64 bits:
// ‐‐‐‐‐‐‐‐
// unused:25 hash:31 ‐‐>| unused:1 age:4 biased_lock:1 lock:2 (normal object)
// JavaThread*:54 epoch:2 unused:1 age:4 biased_lock:1 lock:2 (biased object)
// PromotedObject*:61 ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐>| promo_bits:3 ‐‐‐‐‐>| (CMS promoted object)
// size:64 ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐>| (CMS free block)
//
// unused:25 hash:31 ‐‐>| cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && normal object)
// JavaThread*:54 epoch:2 cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && biased object)
// narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ‐‐‐‐‐>| (COOPs && CMS promoted object)
// unused:21 size:35 ‐‐>| cms_free:1 unused:7 ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐>| (COOPs && CMS free block)

JVM - 剖析Java对象头Object Header之对象大小相关推荐

  1. JVM - 剖析Java对象头Object Header之指针压缩

    文章目录 Pre 指针压缩 论证压缩效果 UseCompressedOops & UseCompressedClassPointers [指针压缩]开启 VS 关闭 指针压缩的目的 为什么堆内 ...

  2. java的头怎么写_JAVA对象布局之对象头(Object Header)

    由于Java面向对象的思想,在JVM中需要大量存储对象,存储时为了实现一些额外的功能,需要在对象中添加一些标记字段用于增强对象功能 .在学习并发编程知识synchronized时,我们总是难以理解其实 ...

  3. JAVA对象布局之对象头(Object Header)

    由于Java面向对象的思想,在JVM中需要大量存储对象,存储时为了实现一些额外的功能,需要在对象中添加一些标记字段用于增强对象功能 .在学习并发编程知识synchronized时,我们总是难以理解其实 ...

  4. 什么是一等对象 first-class object(第一类对象)?

    什么是一等对象 first-class object(第一类对象)? 文章目录 什么是一等对象 first-class object(第一类对象)? 0. 参考资料 1. 定义 0. 参考资料 htt ...

  5. java线程堆栈_深入JVM剖析Java的线程堆栈

    在这篇文章里我将教会你如何分析JVM的线程堆栈以及如何从堆栈信息中找出问题的根因.在我看来线程堆栈分析技术是Java EE产品支持工程师所必须掌握的一门技术.在线程堆栈中存储的信息,通常远超出你的想象 ...

  6. 【Java】Java 对象头 真的是 32位 吗?

    1.概述 HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域: 对象头(Header) 实例数据(Instance Data) 对齐填充(Padding). 是真的吗?假的! 假的!!! ...

  7. 64位JVM的Java对象头详解

    关注"Java艺术"一起来充电吧! 我们编写一个Java类,编译后会生成.class文件,当类加载器将class文件加载到jvm时,会生成一个Klass类型的对象(c++),称为类 ...

  8. java对象头_浅谈java对象结构 对象头 Markword

    概述 对象实例由对象头.实例数据组成,其中对象头包括markword和类型指针,如果是数组,还包括数组长度; | 类型 | 32位JVM | 64位JVM| | ------ ---- | ----- ...

  9. 深入理解JVM(1)——Java内存区域与Java对象

    最近放暑假在家,没有实验室的工作要做,正好趁这个时间恶补了之前一知半解的JVM知识,使用的主要学习资料是周志明大大的<深入理解Java虚拟机--JVM高级特性与最佳实践>,我仔细拜读了两遍 ...

最新文章

  1. PPP协议的CHAP验证
  2. RxJs SwitchMapTo 操作符之移花接木
  3. 实现tree系统命令
  4. 160 - 5 ajj.2
  5. 第四十期:2019年度十大Web开发趋势
  6. python集群到hadoop_如何使用Hadoop流在本地Hadoop集群中运行MRJob?
  7. composer中文阿里云镜像地址
  8. 会动的图解 | 既然IP层会分片,为什么TCP层也还要分段?
  9. 【译】Tim Rose 的kibana插件教程-自定义App插件
  10. string中内容的访问
  11. VB 按指定编码格式写入文本文件
  12. Spark中 RDD之coalesce与repartition区别
  13. MySQL主从复制 + Mycat实现读写分离
  14. java uml Rose_Rational Rose与UML教程
  15. 050、动手实验:使用 jstat 摸清线上系统的JVM运行状况
  16. 谈谈web打印快递单及经验
  17. excel表格打印每页都有表头_Excel打印时如何实现每一页纸上都有表头?
  18. springboot学习(六十七) springboot项目通过gradle-docker-plugin插件构建为doker镜像并推送至镜像私服
  19. oracle脏读查询,没有进行commit操作的数据是否能被查询到,关于oracle的脏读和隔离级别...
  20. EP Henry推出世界首批用二氧化碳固化的Solidia Concrete制造的预制产品

热门文章

  1. mysql 5.6 双向互备_mysql双主互备
  2. OpenCV-Python Feature2D 特征点检测 (SIFT,SURF)
  3. python 、example
  4. 如何将html表单转换成url,JS表单传值和URL编码转换
  5. centos7 mysql读写监控_Centos7 Zabbix监控mysql
  6. 论文笔记:Integrating Classification and Association Rule Mining (即,CBA算法介绍)
  7. matlab画一个局部放大的图中图
  8. 深度2万字好文:图像处理-基于 PyTorch 的 YOLO v5 表情识别(附源代码)
  9. Python简明教程
  10. 新浪微博API OAuth 2 Python客户端