深入浅出JVM(一)之Hotspot虚拟机中的对象

news2024/12/23 18:11:52

本篇文章思维导图

image-20210330233053370.png

对象的创建

对象的创建可以分为五个步骤:检查类加载,分配内存,初始化零值,设置对象头,执行实例构造器

类加载检查
  • HotSpot虚拟机遇到一条new指令,会先检查能否在常量池中定位到这个类的符号引用,检查这个类是否类加载过

    • 没有类加载过就去类加载
    • 类加载过就进行下一步分配内存
分配内存

对象所需的内存在类加载完成后就可以完全确定

分配内存方式

虚拟机在堆上为新对象分配内存,有两种内存分配的方式:指针碰撞,空闲列表

  • 指针碰撞

    • 使用场景: 堆内存规整整齐

    • 过程: 使用过的空间放在一边,空闲的空间放在另一边,中间有一个指针作为分界点指示器,把新生对象放在使用过空间的那一边,中间指针向空闲空间那边挪动一个新生对象的内存大小的距离即可

image-20201028174425589.png

特点:简单,高效,因为要堆内存规整整齐,所以垃圾收集器应该要有压缩整理的能力

  • 空闲列表

    • 使用场景: 已使用空间和空闲空间交错在一起
    • 过程: 虚拟机维护一个列表,列表中记录了哪些内存空间可用,分配时找一块足够大的内存空间划分给新生对象,然后更新列表
    • 特点: 比指针碰撞复杂, 但是对垃圾收集器可以不用压缩整理的能力
分配内存流程

分配内存流程(栈--老年代--TLAB--Eden)

因为在堆上为对象分配内存,内存不足会引起GC,引起GC可能会有STW(Stop The World)影响响应

为了优化减少GC,当对象不会发生逃逸(作用域只在方法中,不会被外界调用)且栈内存足够时,直接在栈上为对象分配内存,当线程结束后,栈空间被回收,(局部变量也被回收)就不用进行垃圾回收了

开启逃逸分析-XX:+DoEscapeAnalysis满足条件的对象就在栈上分配内存

(当对象满足不会逃逸条件除了能够优化在栈上分配内存还会带来锁消除,标量替换等优化...)

image-20201124164550072.png

  1. 尝试该对象能不能在栈上分配内存
  2. 如果不符合1,且该对象特别的大,比如内存超过了JVM设置的大对象的值就直接在老年代上为它分配内存
  3. 如果这个对象不大,为了解决并发分配内存,采用TLAB 本地线程分配缓冲

TLAB 本地线程分配缓存

堆内存是线程共享的,并发情况下从堆中划分线程内存不安全,如果直接加锁会影响并发性能

为每个线程在Eden区分配小小一块属于线程的内存,类似缓冲区

哪个线程要分配内存就在那个线程的缓冲区上分配,只有缓冲区满了,不够了才使用乐观的同步策略(CAS+失败重试)保证分配内存的原子性

image-123.png

在并发情况下分配内存是不安全的(正在给A对象分配内存,指针还未修改,使用原来的指针为对象B分配内存),虚拟机采用TLAB(Thread Local Allocation Buffer本地线程分配缓冲)和CAS+失败重试来保证线程安全

  • TLAB:为每一个线程预先在伊甸园区(Eden)分配一块内存,JVM给线程中的对象分配内存时先在TLAB分配,直到对象大于TLAB中剩余的内存或TLAB内存已用尽时才需要同步锁定(也就是CAS+失败重试)
  • CAS+失败重试:采用CAS配上失败重试的方式保证更新操作的原子性
初始化零值

分配内存完成后,虚拟机将分配的内存空间初始化为零值(不包括对象头) (零值: int对应0等)

保证了对象的成员字段(成员变量)在Java代码中不赋初始值就可以使用

设置对象头

把一些信息(这个对象属于哪个类? 对象哈希码,对象GC分代年龄)存放在对象头中 (后面详细说明对象头)

执行init方法

init方法 = 实例变量赋值 + 实例代码块 + 实例构造器

按照我们自己的意愿进行初始化

对象的内存布局

对象内存信息

对象在堆中的内存布局可以分为三个部分:对象头,实例数据,对齐填充

  • 对象头包括两类信息(8Byte + 4Byte)

    1. Mark Word:用于存储该对象自身运行时数据(该对象的哈希码信息,GC信息:分代年龄,锁信息:状态标志等)

    2. 类型指针(对象指向它类型元数据的指针):HotSpot通过类型指针确定该对象是哪个类的实例 (如果该对象是数组,对象头中还必须记录数组的长度)

    类型指针默认是压缩指针,内存超过32G时为了寻址就不能采用压缩指针了

  • 实例数据是对象真正存储的有效信息

    1. 记录从父类中继承的字段和该类中定义的字段
    2. 父类的字段会出现在子类字段之前,默认子类较小的字段可以插入父类字段间的空隙以此来节约空间(+XX:CompactFields)
  • 对齐填充

    HotSpot要求对象起始地址必须是8字节整倍数

    所以任何对象的大小都必须是8字节的整倍,如果对象实例数据部分未到达8字节就会通过对齐填充进行补全

分析对象占用字节

Object obj = new Object(); 占多少字节?

导入JOL依赖

 <!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core -->
         <dependency>
             <groupId>org.openjdk.jol</groupId>
             <artifactId>jol-core</artifactId>
             <version>0.12</version>
         </dependency>

image-20201124171137539.png mark word : 8 byte

类型指针: 4 byte

对齐填充 12->16 byte

int[] ints = new int[5]; 占多少内存?

image-20201124171539813.png mark word:8 byte

类型指针: 4 byte

数组长度: 4 byte

数组内容初始化: 4*5=20byte

对齐填充: 36 -> 40 byte

父类私有字段到底能不能被子类继承?

image-20201124173533826.png

子类对象的内存空间中保存有父类私有字段,只是无法使用

栈-堆-方法区结构图

image-20210429190053375.png

对象的访问定位

Java程序通过栈上的reference类型数据来操作堆上的对象

访问方式

对象实例数据: 对象的有效信息字段等(就是上面说的数据)

对象类型数据: 该对象所属类的类信息(存于方法区中)

  • 句柄访问

image-20201109182633606.png - 在堆中开辟一块内存作为句柄池,栈中的reference数据存储的是该对象句柄池的地址,句柄中包含了对象实例数据和对象类型数据 - 优点: 稳定,对象被移动时(压缩或复制算法),只需要改动该句柄的对象实例数据指针 - 缺点: 多一次间接访问的开销

  • 直接指针访问

image-20201109182806454.png

栈中的reference数据存储堆中该对象的地址(reference指向该对象),但是对象的内存布局需要保存对象类型数据

优点: 访问速度快

缺点: 不稳定,对象被移动时(压缩或复制算法),需要改动指针

访问方式是虚拟机来规定的,Hotspot主要使用直接指针访问

总结

本篇文章主要从对象的创建流程(类加载、分配内存、初始化零值、设置对象头、执行实例方法)、对象的内存布局(对象头、实例数据、对齐填充)、访问对象的定位方式(直接指针访问、句柄访问)等层面详细介绍了对象,还在其中穿插了栈上分配、TLAB等内存分配优化以及分析对象占用具体空间

  • 参考资料
    • 《深入理解Java虚拟机》
    • 部分图片来源于网络

本文由博客一文多发平台 OpenWrite 发布!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1460977.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【前端素材】推荐实用的后台管理系统ebazer电商平台模板(附带源码)

一、需求分析 后台管理系统网站是指用于管理和控制网站、应用程序或系统后台运行的管理工具。它通常是网站或应用程序的管理者、管理员或内容编辑人员使用的界面&#xff0c;具有一系列功能来管理用户、内容、数据和系统设置。以下是后台管理系统网站的功能和特点&#xff1a;…

Puppeteer 使用实战:如何将自己的 CSDN 专栏文章导出并用于 Hexo 博客(二)

文章目录 上一篇效果演示Puppeteer 修改浏览器的默认下载位置控制并发数错误重试并发控制 错误重试源码 上一篇 Puppeteer 使用实战&#xff1a;如何将自己的 CSDN 专栏文章导出并用于 Hexo 博客&#xff08;一&#xff09; 效果演示 上一篇实现了一些基本功能&#xff0c;…

压缩感知为什么要进行“不相干欠采样”?

压缩感知理论的三个核心要素。1、不相干性信号欠采样&#xff1b;2、稀疏变换&#xff1b;3、非线性迭代重建。 为了通俗解释“不相干性信号欠采样”&#xff0c;我们可以借用一种生活中的例子——拼图。 例子 想象一下&#xff0c;我们有一张由数百片拼图块组成的完整画面。…

Java项目:20 基于SSM实现的支教管理系统

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 ssm支教管理系统&#xff08;前台后台&#xff09; 前台角色&#xff1a;支教学校志愿者 支教学校功能模块&#xff1a;支教学校查询报名职位…

Oracle conn / as sysdba遇到ORA-01031: insufficient privileges错误

背景 oracle 突然挂了&#xff0c;处于锁定状态&#xff0c;然后打算重新启动一下子。 遂 sqlplus /nolog conn / as sysdba 然后就出现了以下错误。。 ORA-01031: insufficient privileges 1.查了一圈&#xff0c;有说是 计算机 》 管理》本地用户和组》组》ORA_DBA&am…

《Linux运维总结:Ubuntu22.04忘记root密码解决方案》

一、解决方法 1、首先重新启动Ubuntu系统&#xff0c;然后快速按下shift键&#xff0c;以调出grub启动菜单&#xff0c;如下图所示&#xff1a; 2、在这里我们选择第二个&#xff08;Advance options for Ubuntu&#xff09;&#xff0c;选中后按下Enter键&#xff0c;如下图所…

三维GIS开发的就业前景

一、前言 三维GIS是一个伪概念,GIS是地理信息系统&#xff0c;三维GIS就是三维地理信息系统&#xff0c;在课本上&#xff0c;专业概念上&#xff0c;也没有这一说法吧&#xff0c;所以三维GIS&#xff0c;就是技术人员造概念拼凑造出来的&#xff0c;本质上就是GIS三维可视化…

车载软件架构Adaptive AUTOSAR —— 身份和访问管理和加密技术

车载软件架构Adaptive AUTOSAR —— 身份和访问管理和加密技术 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师(Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。…

FreeRTOS学习笔记——(任务调度)

这里写目录标题 一、开启任务调度器&#xff08;熟悉&#xff09;二、启动第一个任务&#xff08;熟悉&#xff09;2.1&#xff0c;prvStartFirstTask ()2.2&#xff0c; vPortSVCHandler () 三、任务切换&#xff08;掌握&#xff09; 一、开启任务调度器&#xff08;熟悉&…

【C++初阶】类和对象(中)

目录 一.类的6个默认成员函数 1.知识引入 ​编辑 2.构造函数 (1)概念 (2)语法特性 (3)特征 ①问题引入1 ②问题引入2 &#xff08;缺少默认构造函数&#xff09; 3.析构函数 (1)概念 (2)特性 4.拷贝构造函数 (1)概念 (2)特征 ①拷贝构造函数是构造函数的一…

css伪类函数 :is()、:where()、:has()、:not()

本文主要描述:is()、:where()、:has()、:not()&#xff0c;四个方法大部分内容相同&#xff0c;首先主要讲:is()方法&#xff0c;并根据:is()方法与:where()、:has()、:not()方法的不同来说明这三种方法的特性 :is() 使用方法 选择器特定性 安全性 伪类和伪元素的支持 :前…

Java 后端面试指南

面试指南 TMD&#xff0c;一个后端为什么要了解那么多的知识&#xff0c;真是服了。啥啥都得了解 MySQL MySQL索引可能在以下几种情况下失效&#xff1a; 不遵循最左匹配原则&#xff1a;在联合索引中&#xff0c;如果没有使用索引的最左前缀&#xff0c;即查询条件中没有包含…

【elasticsearch实战】知识库文件系统检索工具FSCrawler

需求背景 最近有一个需求需要建设一个知识库文档检索系统&#xff0c;这些知识库物料附件的文档居多&#xff0c;有较多文档格式如&#xff1a;PDF, Open Office, MS Office等&#xff0c;需要将这些格式的文件转化成文本格式&#xff0c;写入elasticsearch 的全文检索索引&am…

YOLO-World:实时开放词汇目标检测

paper&#xff1a;https://arxiv.org/pdf/2401.17270.pdf Github&#xff1a;GitHub - AILab-CVC/YOLO-World: Real-Time Open-Vocabulary Object Detection online demo&#xff1a;https://huggingface.co/spaces/stevengrove/YOLO-World 目录 0. 摘要 1. 引言 2. 相关工…

解决docker中运行的jar包连不上数据库

目录 数据库主机地址设置问题&#xff1a; 网络连接问题&#xff1a; 数据库端口映射&#xff1a; 数据库认证问题&#xff1a; 数据库服务是否正常运行&#xff1a; 日志查看&#xff1a; 如果在 Docker 中运行的 JAR 包无法连接到数据库&#xff0c;有几个可能的原因和…

优秀自媒体工作者常用的7款ai写作工具! #AI写作#AI写作

我们做自媒体运营&#xff0c;想要快速的创作内容&#xff0c;提供文章的创作速度是我们的目标&#xff0c;我们别的大佬可以很快地就创作出一篇内容&#xff0c;而自己墨迹半天确出不了一个字呢&#xff1f;其实这关乎到创作技巧&#xff0c;下面小编就跟大家分享如何利用自媒…

Linux的Ubuntu的APT使用

Linux的Ubuntu的APT使用 apt 介绍 apt 是 Advanced Packaging Tool 的简称&#xff0c;是一款安装包管理工具。在 Ubuntu 下&#xff0c;我们可以使用 apt 命令进行软件包的安装、删除、清理等&#xff0c;类似于 Windows 中的软件管理工具。 Ubuntu 软件操作的相关命令 su…

SD-WAN专线:助力企业海外社交媒体推广

随着全球化的发展&#xff0c;越来越多的企业将目光投向海外市场&#xff0c;而在海外市场推广中&#xff0c;社交媒体平台成为了一个重要的推广渠道。然而&#xff0c;很多企业在海外社交媒体推广过程中都会遇到网络问题&#xff0c;传统的VPN解决方案往往存在IP被封、网络不稳…

32单片机基础:GPIO输入

1.1按键控制LED 按键介绍&#xff1a; 两种方式&#xff0c;我们一般用下接的方式。 第一个图&#xff1a;注意点。当按键按下&#xff0c;PA0接地&#xff0c;被置为低电平&#xff0c; 但是一旦按键松手&#xff0c;PA0悬空&#xff0c;引脚电压不确定。所以无论怎么读引脚…

MySQL 核心模块揭秘 | 06 期 | 事务提交之前,binlog 写到哪里?

1. 准备工作 参数配置&#xff1a; binlog_format ROW binlog_rows_query_log_events OFF创建测试表&#xff1a; CREATE TABLE t_binlog (id int unsigned NOT NULL AUTO_INCREMENT,i1 int DEFAULT 0,str1 varchar(32) DEFAULT ,PRIMARY KEY (id) USING BTREE ) ENGINEIn…