帮你深入理解 JAVA 对象创建的过程

深入理解Java对象创建过程:从类加载到初始化的完整流程 在Java编程中,对象的创建是一个基础但极其重要的概念。理解对象从类加载到初始化的完整流程,对于编写高效、可靠的Java程序至关重要。本文将深入探讨Java对象创建的完整生命周期,包括类加载、验证、准备、解析、初始化、实例化等关键阶段,并通过代码示例、图表和对比表格帮助读者全面掌握这一过程 阅读详情

说明:本文中的JVM限于HotSpot JVM,详细介绍了,对象在哪里创建、创建的步骤是什么、创建之后的对象长什么样、以及想要使用该对象的时候如何访问。

1 对象在哪里创建

这个问题,就是在你买房子之前,要确定在哪里买。排除房产投资什么的,肯定是在你的工作地买啦。

Java 是面向对象的编程语言,那么,对象到底是在哪里创建的呢?

首先明确一点,几乎所有的对象实例和数组都在堆中分配。这里需要了解 JVM 内存的划分,详见个人另一篇博客JVM 内存划分、GC 机制与性能优化
这里写图片描述

看上面的图,对象优先在Eden中分配,Eden空间不够的时候,会触发一次Minor GC。当需要创建大对象(需要大量连续内存空间的java对象)的时候,则会放入老年代中。如果Major GC之后还是老年代不足,就会直接抛出异常。

2 对象如何创建

这个过程可以概括为:
检查是否进行过类加载——分配内存给新生对象——分配的空间初始化为零值(不包括对象头)——设置对象头——init

听起来太抽象?好吧,换一种表述方式:
检查房地产公司是否合法——确定要买100平米户型——清空房间内原本装修遗留的建材——房子和户主信息匹配登记——房产证下来

下面分别详细阐述:

2.1 检查是否进行过类加载

需要创建一个对象的时候,JVM首先会去检查这个指令的参数能否在常量池中定位到一个类的符号引用,并且检查这个符号引用的类是否已经被加载、解析过。如果没有,必须先执行相应的类加载过程。类似于买房子的时候,先要检查这个房地产公司是不是在工商局注册的合法公司,有没有土地买卖权,购买者的户口在当地符不符合限购令的规定啊等等。

2.2 分配内存给新生对象

类加载检查通过后,为新生对象分配内存。对象需要的内存大小在类加载完成后就可以完全确定。分配内存的过程,类似于你要从这个开发商的楼盘中买个100平米的房子,出了100平米的钱,就得给你100平米房间的钥匙。分配的算法有两种:

内存分配算法适用于算法描述
指针碰撞Serial、ParNew收集器堆中内存绝对规整,一边是用过的,一边是未使用的,二者之间的分界点放一个指针。需要分配内存给一个对象的时候,就把指针向空闲方向移动一段与对象大小相等的距离
空闲列表CMS收集器空闲区域与使用过的区域交错排列,JVM维护一个列表,里面记录着哪块是可用的。分配的时候从表中找出合适大小的空间即可

接下来,每天那么多人去看房子,可能出现你刚准备交首付,另一个人也看上了同一个房子要付款,也就是所谓的创建对象时的并发安全问题。这个问题有两种解决方案:

  • CAS加失败重试
  • 每个线程在堆中预先分配一小块内存(TLAB,本地线程分配缓冲)。哪个线程需要分配内存,就在哪个线程的TLAB上分配,只有TLAB用完要分配新的TLAB时,才同步锁定。

2.3 分配的空间初始化为零值(不包括对象头)

内存分配完成后,虚拟机将该内存空间初始化为零值(不包括对象头)。为什么要进行这样的操作?对象的实例字段在java代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型对应的零值。

这个过程类似于,开发商开发楼盘的时候,首先要把每个房间的墙、门砸好,窗户安好,下水道通了等等。房间里就会遗留下来各种木头、梯子、油漆桶等等,这时候就要先把这些遗留材料清空掉,能保证你从旧房子里搬家具过来就可以直接住。但是对象头绝对不能清空,对象头清空了就没人知道这个房子是不是你的了。

2.4 设置对象头

JVM设置对象的对象头,包括该对象是哪个类的实例,哈希码,GC年龄分代等信息。对象头后面会详细讲。这个过程类似于房子和户主信息匹配登记。

2.5 init

上面的工作之后,对JVM来说,新的对象已经创建好了。但是对于程序员来说,这一切才刚刚开始。执行new指令后,接着执行init
方法,对程序员来说,这个对象才真正可用。

这个过程类似于,开发商给你钥匙,你可以住进去了。但是这个房子真正属于你(拥有买卖权),得等到房产证下来。

3 对象到底长什么样

这里我们需要了解的是你所购买的房屋的结构,几室几厅,厕所在哪里等等。

对象分为三部分:对象头、实例数据、对齐填充

item详述
对象头分为两部分,一是用于存储对象自身的运行时数据,包括哈希码、GC年龄分代、锁标志状态、线程持有的锁、偏向线程ID、偏向时间戳等等,官方称为“Mark Word”。另一部分是类型指针,JVM通过该指针确定该对象是哪个对象的实例
实例数据对象的具体内容
对齐填充并非必然存在,只是因为JVM中对象大小必须是八字节的整数倍,该部分用来补全

注意,普通java对象的元数据信息可以确定该对象的大小,但是数组不可以。因此数组的对象头还应有一块存储数组长度的数据。

4 对象如何被访问

当你创建一个对象之后,为了使用,总得先访问该对象。

首先需要复习一个知识点。Java虚拟机栈中,存储局部变量表、操作数栈、动态链接、方法返回地址和一些额外的附加信息。其中局部变量表存放了三个信息:

  • 各种基本数据类型(boolean、byte、char、short、int、float、long、double)
  • 对象引用(reference)
  • returnAddress地址(指示JVM的指令执行到哪一行)
    也就是说,访问的起始点,永远是局部变量表中的对象引用(reference)。

4.1 通过句柄访问

这里写图片描述

对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要被修改

4.2 通过直接指针访问
这里写图片描述

速度更快,节省了一次指针定位的时间开销,HotSpot采取的就是这种方式。

原文转自
http://blog.youkuaiyun.com/antony9118/article/details/53055368

java通过可视化界面画出一个房子 3、实验内容:数组和对象数组的使用 实验题目1:补充面向对象实验——一栋房子 设计类画出如下的房子 点类 Point类 属性 x,y 构造函数 一组set方法 一组get方法 圆类 Circle 属性 r 构造函数 一组set方法 一组get方法 门类 Door类 属性 左上角的位置(点) 长 宽 圆形把手(圆) 构造函数 一组set方法 一组get方法 窗户类 Window类 属性 左上角的位置(点) 长 宽 长方向的等分数 宽方向的等分数 构造函数 一组set方法 一组get方法 房子类 House类 属性 房屋屋顶左下角的坐标(点类) //屋顶是个三角形 房屋屋顶右下角的坐标(点类) 屋顶顶点的坐标(点类) 正屋高度 存放门的数组 存放窗户的数组 构造函数 一组set方法 一组get方法 BuildHouse 类 void paint(Graphics g){ 绘制一所如上图所示的房子 } 立即下载

相关推荐

matlab 三维绘图 抛光,瓷砖抛光过程建模与仿真

:瓷砖抛 光过程 建模与仿真朱 成 就(广 东工业大学 机 电工程 学院, 广东广州 )摘要 :瓷砖的抛磨影响 因素众 多 ,实际磨削加工时容易出现漏抛 、返抛现象 。对陶瓷抛光机磨头进行运动学分析 ,并基于不 同粒度号 的磨 粒在一定压力下的加工深度模型 ,探讨抛光机磨 头转 速 、横梁摆动频率 、传送速度对瓷砖抛光加工表 面均匀性 的影响,然 后结合 磨削机理使 用 对陶瓷抛光过程进行仿真 ...

weixin_36331058的博客 747

Java对象内存布局通俗解析:对象头、实例数据与对齐填充

对象头:JVM的“快递标签”,记录对象管理信息。实例数据:你的业务属性,按声明顺序存放。对齐填充:JVM自动加的“泡沫”,保证内存访问效率。工具推荐:JOL可视化分析对象实际内存结构。掌握Java对象的内存布局,有助于你写出更高效、可控的Java代码。如有疑问,欢迎留言讨论!

IT技术学习与工作笔记分享 990

软件工程大作业——图书管理系统/图书个性化推荐与实现系统

软件工程期末大作业,图书管理系统,包含ER图、程序流程图、属性图、结构图

2401_82857325的博客 3646

java内存对齐_Java对象内存布局对齐填充等价形式推导

在《Java对象的内存布局》中给出了32位HotSpot虚拟机和64位HotSpot虚拟机下Java对象内存布局的对齐填充规则,为了便于在“基于Java对象内存布局计算Java对象大小的算法”中应用这些对齐填充规则,本文尝试推导这些对齐填充规则的等价形式。本文结构分为两个部分:1)一条定理;2)分32位HotSpot虚拟机和64位HotSpot虚拟机分别进行推导。备注:以“Ak”表示“k-对齐”操...

weixin_28871989的博客 1226

为什么你的Mac蓝牙总断连?深入解析硬件干扰与系统设置避坑

本文深入解析Mac蓝牙频繁断连的原因,包括硬件干扰(如WiFi同频干扰、USB设备电磁干扰)和系统设置问题,并提供详细的优化方案和诊断工具(如blueutil)使用指南,帮助用户有效解决蓝牙稳定性问题。

ik67890123的博客 679

从零开始的机械臂yolov5抓取gazebo仿真(一)

本文介绍了如何将机械臂模型导出为URDF

qq_48427527的博客 1万+

比喻帮你深入理解 JAVA 对象

说明:本文中的JVM限于HotSpot JVM,详细介绍了,对象在哪里创建、创建的步骤是什么、创建之后的对象长什么样、以及想要使用该对象的时候如何访问。如有转载,请标明出处。1 对象在哪里创建Java 是面向对象的编程语言,那么,对象到底是在哪里创建的呢?首先明确一点,几乎所有的对象实例和数组都在堆中分配。这里需要了解 JVM 内存的划分,详见个人另一篇博客JVM 内存划分、GC 机制与性能优化看上

橙子wj的博客 1275

Claude Code设置中文输出指南

Claude Code 的语言配置其实并不复杂,只要做好全局的默认设置,再加上一些小的提醒技巧,就能完全避免突然切换英文的问题,让你全程用中文流畅地和 AI 助手协作,不用再被语言问题打断工作节奏,真正提升开发效率。

篮球界最会写bug的人;程序猿中打球最菜的人。 2207

随笔——java的比喻

偶来想起一些东西。想记录下载 一、java之路的比喻 二、抽象类与接口的比喻 面试的时候有人问我你什么时候使用抽象类,什么时候使用接口。 当时我对他说:最好用接口,不行再用抽象类,类是单继承,留给关键时刻用。有补充说:接口相当于一种规则。抽象类相当于一个模板,有存在,有等你实现的。 我的回答并没有的到赞同。 今天再次想起这件事。有了一个感觉不错的比喻。 假如你写的类是一个学生。此时学

愿见世间如清水 1020

高通开发系列 - Bootloader之lk匹配dtb和dtbo中msm-id和board-id的知识

lk匹配dtb和dtbo中的msm-id和board-id等知识

fulinux的博客 4244

使用 MATLAB/Simulink 对一个开关磁阻电机进行建模

*开关磁阻电机(Switched Reluctance Motor, SRM)**是一种新型的无刷电机,以其简单的机械结构、宽广的调速范围和较高的效率在工业应用中得到了广泛关注。SRM的独特之处在于其定子和转子均为凸极结构,并且通过改变绕组电流的方向来实现转矩的产生和控制。本教程将详细介绍如何使用对一个开关磁阻电机进行建模,并探讨其基本控制策略,特别是针对双凸极结构的SRM。本文介绍了如何使用构建一个开关磁阻电机的双凸极结构模型,并探讨了其基本控制策略。

amy_mhd的博客 203

【Java对象解析】不得不了解的对象头

一:对象头 HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。   HotSpot虚拟机的对象头(Object Header)包括两部分信息,第一部分用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等,这部分数...

扬帆舟的博客 4万+

ESP32 VSCode开发环境配置

ESP32 VSCode开发环境配置

qq_53529450的博客 507

深入理解 Java 虚拟机(五)~ 对象的创建过程

本文详细介绍了对象的创建过程如类的加载、内存的分配和初始化,分配内存时的同步方式,对象的初始化操作。还介绍了对象的内存布局,如对象头、实例数据、对齐填充。最后介绍了 Hotspot 如何进行对象的访问定位。

Chiclaim 2983

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

深入理解Java对象的创建过程:类的初始化与实例化

在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的。在实例化一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用类构造器完成类的初始化。在类初始化过程中或初始化完毕后,根据具体情况才会去对类进行实例化。本文试图对JVM执行类初始化和实例化的过程做一个详细深入地介绍,以便从Java虚拟机的角度清晰解剖一个Java对象的创建过程。

Rico's Blogs 19万+

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

深入理解JVM:java对象的创建过程?

Step1:类加载检查 虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执行相应的类加载过程。 Step2:分配内存 在类加载检查通过后,接下来虚拟机将为新生对象分配内存。对象所需的内存大小在类加载完成后便可确定,为对象分配空间的任务等同于把一块确定大小的内存从 Java 堆中划分出来。分配方式有 “指针碰撞” 和 “空闲列表” 两种,选择那种分配方式由 Java 堆是否规整决定.

~悟空的定海神针~ 1919

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

图文深入理解java对象从创建到回收都经历了什么

每个java对象都是有生命周期的,就像一个人的生命一样,从孕育到出生到成长变老最后由归于自然。笔者认为,Java对象的整个生命周期可以分为两个大的阶段:即创建阶段和运行阶段(包含对象的回收和消亡)。本篇将会图文深入介绍java对象的整个生命过程。

qq_45732829的博客 2552

对象的创建过程

一个Java对象的创建过程就是类实例化的过程,往往会包括类初始化的过程,在第一次创建一个类的对象时,就需要对类进行初始化,以后再创建这个类的对象时,只需进行类的实例化,就不需要进行类的初始化了。

cxbtdd的博客 1204

Java对象的创建过程

本文主要讲了对象创建的五大过程以及每一步的具体作用,后续为了使用Java对象因而讲了一些对象访问定位相关的知识。

Startapi的博客 569

深入理解 Java 虚拟机:对象的创建过程

JVM 知识点整理:对象的创建过程类加载分配内存分配方式一:指针碰撞分配方式二:空闲列表如何选择?线程安全问题 类加载 虚拟机遇到一条 new 指令时,首先检查,指令的参数是否能在常量池种定位到一个类的符号引用,并且检查这个符号引用的类是否已经被加载、解析、初始化过,如果没有那必须执行相应的类加载过程。 比如:String str = null; 这就意味着类已经被加载,创建对象时这步类加载就不要...

乐之终曲 1165

Java对象创建的过程

1. 执行类加载过程 虚拟机遇到一条new指令时,首先检查该对象对应的类是否已被加载、解析和初始化过,如果没有,则先执行相应的类加载过程。 2. 为对象分配内存 类加载检查通过后,虚拟机就会为新生对象分配内存(对象所需的内存大小在类加载完成后便可完全确定),为对象分配内存的任务相当于从Java堆中划分出一块确定大小的内存,根据Java堆中内存是否是规整的(是否规整由采用的垃圾收集器是否带有压缩整理...

litexy 268

【JVM】一个Java对象的创建过程

Object obj = new Object(); Java中创建对象时,需要经过5个阶段,分别是:类加载检查、分配内存、初始化零值、设置对象头、执行init方法。 1、类加载检查 当JVM执行到一条new指令时,先检查这条指令的参数是否能在常量池定位到这个类的符号引用,同时检查这个类是否已被加载、解析、初始化,如果没有则会先进行类加载过程。 2、分配内存 在类加载检查后,JVM为新对象分配内存。对象所需的内存大小在类加载完成后可确定,因此分配内存的过程就是把一块确定大小的内存从堆中划分出来。分配方式有指

Steven_L_的博客 3492

问:梳理JAVA对象创建的过程?

Java对象创建包括类加载、内存分配、内存初始化、对象头设置和构造函数执行。JVM自动处理这些步骤,开发者无需直接操作。理解此过程有助于优化代码性能、排查内存问题,并深入掌握Java内存管理机制。

技术铺掌柜 1022

java中new一个对象要经历哪些过程

我们要了解new一个对象经历哪些过程,就要知道new对象之前会做什么事情。 首先Java在new一个对象的时候,会先查看对象所属的类有没有被加载到内存,如果没有的话,就会先通过类的全限定名将对象所属的.class文件加载到内存中。加载并初始化类完成后,再进行对象的创建工作。 我们先假设是第一次使用该类,这样的话new一个对象就可以分为两个过程:加载并初始化类和创建对象。 一、类加载过程(...

Evan's Blog ٩(๑❛ᴗ❛๑)۶ 5889

深入理解对象创建过程

首先我们要明白一点:运行时常量池里面究竟存放了哪些东西? Class文件中除了有类的版本、字段、方法、接口等信息以外,还有一项信息就是静态常量池(Constant Pool Table),这个常量池存放编译期生成的各种字面量和符号引用,这部分内容将在类加载进入方法区的运行时常量池存放。 所以运行时常量池存放了基本类型数据(只存一个字节的常量,像int类型,就只能存-128~127,超出这个范围...

u011246329的博客 278

对象创建的过程

摘要: 本文详细解析Java对象创建的完整流程,通过Student类示例展示从new关键字执行到对象可用的7个关键步骤: 类加载检查:确保类已加载(静态代码块仅执行一次)。 内存分配:根据对象大小在堆中划分空间(采用指针碰撞或空闲列表算法)。 默认初始化:隐式设置成员变量零值(如name=null)。 对象头设置:标记哈希码、类元信息等身份标签。 实例初始化:先执行实例初始化块,再调用构造器(如age先被初始化为18后被覆盖)。 引用赋值:将堆地址关联到栈中的引用变量。 对象可用:通过引用操作对象。

qq_59219765的博客 1136
上一篇: JVM内存分配样例
下一篇: 事务原理:ACID,CAP和BASE理论及分布式事务一致性案例
牧竹子
博客等级 码龄17年 572粉丝 233原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值