Java对象内存布局和对象头

简介: Java对象内存布局和对象头
Object obj = new Object();  //new 一个对象,占内存多少? 没有实例数据的话,就是16个字节


1、对象的内存布局


HotSpot虚拟机里,对象在堆内存中的存储布局可以划分为三个部分:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)

1673417457180.jpg

2、对象在堆内存中的存储布局

1673417470151.jpg

Mark Word:对象标记

Class Pointer:类元信息(又叫类型指针)


对象内部结构分为:对象头、实例数据、对齐填充(保证8个字节的倍数,8、16、24。。。)。

对象头分为对象标记(markOop)和类元信息(klassOop),类元信息存储的是指向该对象类元数据(klass)的首地址。


1、对象头


1、对象标记Mark Word

1673417500752.jpg

1673417511767.jpg

在64位系统中,Mark Word占了8个字节,类型指针占了8个字节,一共是16个字节

1673417519503.jpg

对象标记(Mark Word)默认存储对象的HashCode、分代年龄和锁标志位等信息。

这些信息都是与对象自身定义无关的数据,所以MarkWord被设计成一个非固定的数据结构以便在极小的空间内存存储尽量多的数据。

它会根据对象的状态复用自己的存储空间,也就是说在运行期间MarkWord里存储的数据会随着锁标志位的变化而变化。


2、类元信息(又叫类型指针)


1673417540723.jpg

对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。


3、对象头多大


在64位系统中,Mark Word占了8个字节,类型指针占了8个字节,一共是16个字节。


2、实例数据


存放类的属性(Field)数据信息,包括父类的属性信息(类属性),如果是数组的实例部分还包括数组的长度,这部分内存按4字节对齐


3、实例填充


虚拟机要求对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐这部分内存按8字节补充对齐。


http://openjdk.java.net/groups/hotspot/docs/HotSpotGlossary.html


http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/89fb452b3688/src/share/vm/oops/oop.hpp

1673417578027.jpg

_mark字段是mark word,_metadata是类指针klass pointer, 对象头(object header)即是由这两个字段组成,这些术语可以参考Hotspot术语表,


每个对象都有class pointer(类型指针)和 header word(对象标记)


4、Mark Word

1673417595907.jpg


1、oop.hpp

1673417607983.jpg

2、markOop.hpp


hash: 保存对象的哈希码
age: 保存对象的分代年龄
biased_lock: 偏向锁标识位
lock: 锁状态标识位
JavaThread* :保存持有偏向锁的线程ID
epoch: 保存偏向时间戳

1673417625355.jpg

markword(64位)分布图,对象布局、GC回收和后面的锁升级就是对象标记MarkWord里面标志位的变化

1673417633657.jpg

5、Object obj = new Object()解析


1、JOL证明


JOL

<!--
定位:分析对象在JVM的大小和分布
-->
<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.9</version>
</dependency>
public class MyObject
{
    public static void main(String[] args){
        //VM的细节详细情况
        System.out.println(VM.current().details());
        //所有的对象分配的字节都是8的整数倍。
        System.out.println(VM.current().objectAlignment());
    }
}

1673417676014.jpg

public class JOLDemo
{
    public static void main(String[] args)
    {
        Object o = new Object();
        System.out.println( ClassLayout.parseInstance(o).toPrintable());
    }
}

1673417694177.jpg

OFFSET 偏移量,也就是到这个字段位置所占用的byte数
SIZE 后面类型的字节大小
TYPE 是Class中定义的类型
DESCRIPTION DESCRIPTION是类型的描述
VALUE VALUE是TYPE在内存中的值


2、换成其他对象

1673417745283.jpg


3、对象分代年龄


GC年龄采用4位bit存储,最大为15,例如MaxTenuringThreshold参数默认值就是15


添加运行参数:-XX:MaxTenuringThreshold=16

1673417756710.jpg

4、默认开启压缩说明


运行参数:把启动配置参数打印出来

java -XX:+PrintCommandLineFlags -version


1673417763967.jpg

说明运行默认开启压缩类型指针


手动关闭压缩再看看


+就是开始,-就是关闭

-XX:-UseCompressedClassPointers

1673417781223.jpg

手动配置,关闭压缩指针,就没有了对齐填充,直接到 8 + 8 = 16字节

相关文章
|
24天前
|
存储 缓存 安全
Java内存模型深度解析:从理论到实践####
【10月更文挑战第21天】 本文深入探讨了Java内存模型(JMM)的核心概念与底层机制,通过剖析其设计原理、内存可见性问题及其解决方案,结合具体代码示例,帮助读者构建对JMM的全面理解。不同于传统的摘要概述,我们将直接以故事化手法引入,让读者在轻松的情境中领略JMM的精髓。 ####
33 6
|
15天前
|
安全 Java 程序员
深入理解Java内存模型与并发编程####
本文旨在探讨Java内存模型(JMM)的复杂性及其对并发编程的影响,不同于传统的摘要形式,本文将以一个实际案例为引子,逐步揭示JMM的核心概念,包括原子性、可见性、有序性,以及这些特性在多线程环境下的具体表现。通过对比分析不同并发工具类的应用,如synchronized、volatile关键字、Lock接口及其实现等,本文将展示如何在实践中有效利用JMM来设计高效且安全的并发程序。最后,还将简要介绍Java 8及更高版本中引入的新特性,如StampedLock,以及它们如何进一步优化多线程编程模型。 ####
21 0
|
25天前
|
存储 算法 Java
Java内存管理深度剖析与优化策略####
本文深入探讨了Java虚拟机(JVM)的内存管理机制,重点分析了堆内存的分配策略、垃圾回收算法以及如何通过调优提升应用性能。通过案例驱动的方式,揭示了常见内存泄漏的根源与解决策略,旨在为开发者提供实用的内存管理技巧,确保应用程序既高效又稳定地运行。 ####
|
17天前
|
存储 监控 算法
Java内存管理深度剖析:从垃圾收集到内存泄漏的全面指南####
本文深入探讨了Java虚拟机(JVM)中的内存管理机制,特别是垃圾收集(GC)的工作原理及其调优策略。不同于传统的摘要概述,本文将通过实际案例分析,揭示内存泄漏的根源与预防措施,为开发者提供实战中的优化建议,旨在帮助读者构建高效、稳定的Java应用。 ####
31 8
|
15天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
16天前
|
缓存 监控 算法
Python内存管理:掌握对象的生命周期与垃圾回收机制####
本文深入探讨了Python中的内存管理机制,特别是对象的生命周期和垃圾回收过程。通过理解引用计数、标记-清除及分代收集等核心概念,帮助开发者优化程序性能,避免内存泄漏。 ####
28 3
|
19天前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
46 5
|
17天前
|
存储 算法 Java
Java内存管理深度解析####
本文深入探讨了Java虚拟机(JVM)中的内存分配与垃圾回收机制,揭示了其高效管理内存的奥秘。文章首先概述了JVM内存模型,随后详细阐述了堆、栈、方法区等关键区域的作用及管理策略。在垃圾回收部分,重点介绍了标记-清除、复制算法、标记-整理等多种回收算法的工作原理及其适用场景,并通过实际案例分析了不同GC策略对应用性能的影响。对于开发者而言,理解这些原理有助于编写出更加高效、稳定的Java应用程序。 ####
|
17天前
|
安全 Java 程序员
Java内存模型的深入理解与实践
本文旨在深入探讨Java内存模型(JMM)的核心概念,包括原子性、可见性和有序性,并通过实例代码分析这些特性在实际编程中的应用。我们将从理论到实践,逐步揭示JMM在多线程编程中的重要性和复杂性,帮助读者构建更加健壮的并发程序。
|
22天前
|
算法 Java 开发者
Java内存管理与垃圾回收机制深度剖析####
本文深入探讨了Java虚拟机(JVM)的内存管理机制,特别是其垃圾回收机制的工作原理、算法及实践优化策略。不同于传统的摘要概述,本文将以一个虚拟的“城市环卫系统”为比喻,生动形象地揭示Java内存管理的奥秘,旨在帮助开发者更好地理解并调优Java应用的性能。 ####