通过前一节《Java内存区域(运行时数据区)》大概知道了虚拟机的内存情况。

本节内容将总结一下 HotSpot 虚拟机在 Java 堆中对象分配、布局和访问的全过程。


1. 对象的创建

下图是 Java 对象的创建过程,建议最好是能默写出来,并且要掌握每一步在做什么。


Step1:类加载检查

虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执行相应的类加载过程。


Step2:分配内存

类加载检查通过后,接下来虚拟机将为新生对象分配内存

对象所需的内存大小在类加载完成后便可确定,为对象分配空间的任务等同于把一块确定大小的内存从 Java 堆中划分出来。

分配方式有 “指针碰撞” 和 “空闲列表” 两种,选择哪种分配方式由 Java 堆是否规整决定,而 Java 堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定

内存分配的两种方式:(掌握)

选择以上两种方式中的哪一种,取决于 Java 堆内存是否规整。而 Java 堆内存是否规整,取决于 GC 收集器的算法是"标记-清除",还是"标记-整理"(也称作"标记-压缩"),值得注意的是,复制算法内存也是规整的

内存分配并发问题(掌握)

在创建对象的时候有一个很重要的问题,就是线程安全。因为在实际开发过程中,创建对象是很频繁的事情,作为虚拟机来说,必须要保证线程是安全的,通常来讲,虚拟机采用两种方式来保证线程安全:

  • CAS+失败重试: CAS 是乐观锁的一种实现方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。虚拟机采用 CAS 配上失败重试的方式保证更新操作的原子性。
  • TLAB: 为每一个线程预先在 Eden 区分配一块儿内存,JVM 在给线程中的对象分配内存时,首先在 TLAB 分配,当对象大于 TLAB 中的剩余内存或 TLAB 的内存已用尽时,再采用上述的 CAS 进行内存分配

Step3:初始化零值

内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头)。

这一步操作保证了对象的实例字段在 Java 代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。


Step4:设置对象头

初始化零值完成之后,虚拟机要对对象进行必要的设置。

例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的 GC 分代年龄等信息。 这些信息存放在对象头中。

另外,根据虚拟机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。


Step5:执行init方法

在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了。

但从 Java 程序的视角来看,对象创建才刚开始, <init>方法还没有执行,所有的字段都还为零。

所以一般来说,执行 new 指令之后会接着执行 <init> 方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生出来。


2. 对象的内存布局

在 Hotspot 虚拟机中,对象在内存中的布局可以分为 3 块区域:对象头、实例数据和对齐填充

  • Hotspot 虚拟机的对象头包括两部分信息第一部分用于存储对象自身的运行时数据(哈希码、GC 分代年龄、锁状态标志等等),另一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是那个类的实例。
  • 实例数据部分是对象真正存储的有效信息,也是在程序中所定义的各种类型的字段内容。
  • 对齐填充部分不是必然存在的,也没有什么特别的含义,仅仅起占位作用。 因为 Hotspot 虚拟机的自动内存管理系统要求对象起始地址必须是 8 字节的整数倍,换句话说就是对象的大小必须是 8 字节的整数倍。而对象头部分正好是 8 字节的倍数(1 倍或 2 倍),因此,当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。

3. 对象的访问定位

建立对象就是为了使用对象,我们的 Java 程序通过栈上的 reference 数据来操作堆上的具体对象。

对象的访问方式由虚拟机实现而定,目前主流的访问方式有① 使用句柄② 直接指针两种:

  1. 句柄: 如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息;

  2. 直接指针: 如果使用直接指针访问,那么 Java 堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而 reference 中存储的直接就是对象的地址。

这两种对象访问方式各有优势。使用句柄来访问的最大好处是 reference 中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而 reference 本身不需要修改。使用直接指针访问方式最大的好处就是速度快,它节省了一次指针定位的时间开销。

HotSpot虚拟机对象揭秘相关推荐

  1. JVM-02内存区域与内存溢出异常(中)【hotspot虚拟机对象】

    文章目录 思维导图 对象的创建 对象的内存布局 实例数据(Instance Data) 对齐填充(Padding) 对象的访问定位 使用句柄(类似间接指针) 直接指针访问 (HotSpot采用这种方式 ...

  2. Hotspot虚拟机对象探秘

    Hotspot虚拟机对象探秘 对象的创建 java 中提供的几种对象创建方式: 对象的创建主要流程 为对象分配内存 处理并发安全问题 对象的访问定位 句柄访问 直接指针 对象的创建 java 中提供的 ...

  3. JVM hotspot虚拟机对象探秘

    为什么80%的码农都做不了架构师?>>>    本文全部内容均转述自<深入理解Java虚拟机 JVM高级特性与最佳实践(第二版)>2.3节 下载地址:http://pan ...

  4. 深入理解Java虚拟机(二)——HotSpot虚拟机对象

    一.对象的创建 1.检查 虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载.解析和初始化过.如果没有,那必须先执 ...

  5. HotSpot虚拟机对象的创建过程

    1.文中讨论的对象限于普通Java对象,不包括数组和class对象. 2.内存的分配方式由Java堆是否规整来决定,而Java堆是否规整取决于垃圾收集器是否有压缩整理的功能. 3.还需要考虑:对象的创 ...

  6. Java虚拟机对象的探索—对象的内存布局

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

  7. HotSpot虚拟机在Java堆中对对象的管理

    在大概了解了Java虚拟机中内存的大致分布后,接下来就应该了解虚拟机是如何在内存中管理对象的,毕竟Java是一门面向对象的语言,在Java程序的运行过程中会不断有对象创建出来.为了方便,这里仅仅以Ho ...

  8. Hotspot虚拟机的对象

    创建 Step1:类加载检查 虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过.解析和初始化过.如果没有,那 ...

  9. Java对象创建、分配、布局、访问小析(HotSpot虚拟机)(二)

    本文内容总结自周志明先生所编著的<深入理解Java虚拟机-JVM高级特性与最佳实践>此书的经典不必多说.本节内容是对象的内存布局. 在HotSpot虚拟机中,对象在内存中存储的布局可以分为 ...

  10. Java 14 Hotspot 虚拟机垃圾回收调优指南!

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 大鹏123 来源 | www.cnblogs. ...

最新文章

  1. java 文件夹删除_java创建删除文件及文件夹大全
  2. 5G时代,会有什么奇葩事儿?
  3. 学习OpenCV——粒子滤波(网上两篇文章总结)
  4. NYOJ 116 士兵杀敌(二)
  5. mariadb设置root初始密码
  6. Creator-配置MSVC调试器
  7. 前端基础:html基础(css基础和JavaScript基础)/01/B/S网络结构,html文件结构,html标签格式,lt;bodygt;中的一些常用标记
  8. san分布式共享文件系统_基于SAN存储共享卷实现openstack高可用的方法与流程
  9. 华为ENSP的Stelnet、直连、串口连接、telnet连接登录
  10. 关系图谱在风控体系的应用与实践
  11. 记得12306货运系统“抢购空”编写插件--chrome交互式插件的各个部分
  12. 鲁大师2022半年报显卡排行,NVIDIA霸榜,七彩虹成最大赢家!
  13. 7-32 哥尼斯堡的“七桥问题” (欧拉回路)(PAT算法题目集)
  14. 用PV操作写出一个不会出现死锁的哲学家进餐问题
  15. B2C电商项目(第十五天、秒杀后端、异步下单、防止恶意刷单、防止重复秒杀、下单接口隐藏、下单接口限流 )
  16. 2022-12-16 leetcode与蓝桥刷题情况
  17. 香港股市api调用代码返回示例
  18. 响应式Web设计:HTML5和CSS3实战(读书笔记)
  19. 分享一些大公司团队的代码
  20. python京东注册机_Python实现京东自动登录

热门文章

  1. java运行时数据区、程序计数器(pc寄存器)、Java虚拟机栈、栈帧、局部变量表、操作数栈
  2. BigDecimal 加减乘除计算
  3. RocketMQ之消费者顺序消费源码解析
  4. 【java基础】Eclipse Java注释模板设置详解以及版权声明
  5. 线性表接口的实现_Java
  6. cocos2d-x之物理世界(创建物理世界)
  7. nagios介绍及Server安装(三)
  8. HDU-1042 N!
  9. Android Studio 工程项目的结构
  10. BZOJ5212[ZJOI2018]历史