首页 > 其他分享 >[JVM]对象创建过程

[JVM]对象创建过程

时间:2024-09-16 22:12:43浏览次数:8  
标签:Java 对象 创建 虚拟机 内存 JVM 句柄 指针

Java 对象的创建过程

Java对象创建的过程主要分为五个步骤,下面我将详细介绍这五个步骤。

Step1:类加载检查

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

Step2:分配内存

当类加载检查通过后,虚拟机会为新生对象分配内存空间,对象所需内存空间的大小在类加载完成后就已经确定了。为新生对象分配内存空间其实就是在Java堆中划分出一块确定大小的内存分配给新生对象。

分配内存的方式有“指针碰撞”和“空闲列表”两种,选择哪种分配方式取决于Java堆内存是否规整。

内存分配的两种方式

指针碰撞

使用场合:堆内存规整(即没有内存碎片)的情况下。
实现原理:将用过的内存都整合到一边,没有用过的内存放到另一边,中间有一个分界指针,当需要为新对象分配内存空间时,只需要将分界指针向没有用过的内存一侧移动对象内存大小位置即可。

空闲列表

使用场合:堆内存不规整的情况下。
实现原理:虚拟机会维护一个列表,该列表记录了那些内存是可用的,当需要为新对象分配内存空间时,只需要在列表中找一块足够大小的内存分配给对象实例,然后更新列表记录。

选择以上两种方式中的哪一种,取决于 Java 堆内存是否规整。而 Java 堆内存是否规整,取决于 GC 收集器垃圾采用的垃圾收集算法,垃圾收集相关内容我会在后续文章详细介绍。

Step3:初始化零值

内存分配完成后,虚拟机需要将新分配的内存空间都初始化为零值(不包括对象头),这一步操作保证了对象的实例字段可以在Java代码中可以不赋初始值就直接使用,程序能够访问这些实例字段的数据类型所对应的零值。

Step4:设置对象头

初始化零值之后,虚拟机需要对对象头进行必要的设置,例如这个对象是哪个类的实例,如何才能找到这个类的元数据信息,对象的哈希码,对象的GC分代年龄等信息,这些信息会存放到对象头中。另外,根据虚拟机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。

Step5:执行init方法

执行完上面四个步骤后,从虚拟机的角度来看,一个新对象已经产生了,但是从Java程序的角度来看,对象的创建才刚刚开始,init()方法还没有,所有的字段都还是零值,所以,一般来说,执行完new指令后会接着执行init方法,将对象按照程序员的需求来进行初始化,这样一个真正可用的对象才算完全产生出来。

对象的内存布局

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

对象头

对象头由两部分组成:对象标记Mark Word和类元信息(又叫类型指针)组成。

对象标记

对象标记用于存储对象自身的运行时数据,例如哈希码、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等信息,这些信息都是与对象自身定义无关的数据,所以Mark Word被设计成一个非固定的数据结构以便在极小的空间内存存储尽量多的数据。它会根据对象的状态复用自己的存储空间,也就是说在运行期间Mark Word里存储的数据会随着锁标志位的变化而变化。

类型指针

类型指针是对象指向它的类的元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。 并不是所有的虚拟机实现都必须在对象数据上保留类型指针,换句话说查找对象的元数据信息并不一定要经过对象本身。另外,如果对象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小,但是从数组的元数据中无法确定数组的大小。

实例数据

实例数据部分是对象真正存储的有效信息,也是在程序中所定义的各种类型的字段内容,包括从父类继承下来的和本身拥有的字段。

对齐填充

对齐填充部分不是必然存在的,也没有什么特别的含义,仅仅起占位作用。 因为 Hotspot 虚拟机的自动内存管理系统要求对象起始地址必须是 8 字节的整数倍,换句话说就是对象的大小必须是 8 字节的整数倍。而对象头部分正好是 8 字节的倍数(1 倍或 2 倍),因此,当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。

对象的访问定位

建立对象就是为了使用对象,我们的 Java 程序通过栈上的 reference 数据来操作堆上的具体对象。对象的访问方式由虚拟机实现而定,目前主流的访问方式有:使用句柄、直接指针。

句柄

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

直接指针

如果使用直接指针访问,reference 中存储的直接就是对象的地址。
image

两种访问方式比较

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

标签:Java,对象,创建,虚拟机,内存,JVM,句柄,指针
From: https://www.cnblogs.com/DCFV/p/18416679

相关文章

  • [Java面向对象]封装继承多态
    封装、继承和多态是面向对象编程的三大特征。封装封装概念封装就是把抽象出的数据(属性)和对数据的操作(方法)封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作(方法)才能对数据进行操作。封装的好处隐藏实现的细节一个操作具体的实现过程往往很复杂,通过封装用户......
  • 类和对象(1)
    个人主页:Jason_from_China-CSDN博客所属栏目:C++系统性学习_Jason_from_China的博客-CSDN博客所属栏目:C++知识点的补充_Jason_from_China的博客-CSDN博客前言类和对象是C++初阶比较难的篇章,这里的学习深度还是很深的,建议学习的小伙伴比这打一下代码。类的定义格式......
  • Day20笔记-面向对象&类和对象&类中的属性和函数&构造和析构函数
    一、面向对象基础1.概念1.1面向对象的设计思想面向对象是基于万物皆对象这个哲学观点,在Python中,一切皆对象举例说明:​案例一:我想要吃大盘鸡​面向过程面向对象​1.自己去买菜1.委托一个会砍价的人帮忙去买菜​2.自己择菜2.委托一个临时工帮忙择菜​3.自己......
  • Day11.面向对象编程OOP(3)
    多态动态编译:类型:可扩展性即同一种方法可以根据发送对象的不同而采用多种不同的行为方式一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多多态注意事项:多态是方法的多态,属性没有多态父类和子类有联系类型转换异常:ClassCastException存在条件:继承......
  • 函数栈帧的创建与销毁(简单易懂超详细~)
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、什么是函数栈帧1.函数栈帧的创建与销毁2.寄存器3.函数调用创建函数栈帧二、main函数栈帧的创建与销毁1.main函数栈帧的开辟2.main函数中变量的创建3.main函数中Add的调用4.进入Add中去5.......
  • 从零开始:使用Dash创建功能丰富的交互式Web应用程序
    在数据科学和可视化领域,交互式Web应用程序是与用户交互和展示数据的强大工具。Dash是一个用Python构建交互式Web应用程序的开源框架,它结合了Flask、React和Plotly等技术,让开发者能够快速创建功能丰富的数据可视化应用。本文将介绍如何使用Dash来构建交互式Web应用程序,并提供代码示......
  • 文心智能体零代码创建心
    通过使用文心智能体平台来创建智能体的过程。这种方法可以让没有编程经验的人也能快速构建智能体,降低了技术门槛。以下是一些建议和心得:选择合适的平台:文心智能体平台是一个优秀的选择,它提供了零代码和低代码的开发环境,极大地降低了技术门槛。设计对话流程:在创建智能体时,要考虑用户......
  • urllib自定义opener对象设置代理IP
    urllib.request.urlopen()源代码——urlopen()在干什么返回opener.open(url,data,timeout)方法的结果 _opener=None#_opener被赋值为Nonedefurlopen(url,data=None,timeout=socket._GLOBAL_DEFAULT_TIMEOUT,*,cafile=None,capath=None,cadefault=......
  • Mobaxterm 解除session创建限制
    Mobaxterm版本为20.2去除限制步骤1下载github上面的一个开源小项目gitclonehttps://github.com/flygon2018/MobaXterm-keygen.git下载下来后cdMobaXterm-keygenpython3MobaXterm-Keygen.py<UserName><Version>UserName我填的是windows的登录用户名,Versi......
  • 再vue中使用Vuetify 创建app项目
    vue:2Vuetify:2 与vue创建普通项目相同:https://www.cnblogs.com/yansans/p/18342267  vscode打开项目,在项目终端中运行vueaddvuetify@2之后会出现,选择默认即可(回车) 几个选项的解释:1.Vuetify2-ConfigureVueCLI(advanced)解释:这是一个高级选项,允许你对项目......