Java对象创建过程

在日常开发中,我们常常需要创建对象,那么通过new关键字创建对象的执行中涉及到哪些流程呢?本文主要围绕这个问题来展开。

类的加载

创建对象时我们常常使用new关键字。如下

java 复制代码
ObjectA o = new ObjectA();

对虚拟机来讲首先需要判断ObjectA类的元数据有没有加载到方法区,如果没有,则需要先加载并出实话类ObjectA。加载流程如下:

  1. 通过双亲委派机制(父类优先、缓存机制)加载对应类的二进制字节流,将其转化为Class结构存储在方法区
  2. 验证文件格式、元数据、字节码、符号引用的正确性
  3. 准备为类标量分配内存,并初始化类变量
  4. 解析阶段将常亮池中符号引用替换为直接引用,即将符号替换为具体的地址指针或者能定位到的句柄|偏移量等
  5. 初始化阶段是为类变量执行赋值等操作,会执行()方法。

空间分配

经过第一步的类的加载,此时ObjectA的类信息已经完成,其Class对象已构建在堆内,并初始化了其类常量的值。接下来看是为创建ObjectA对象分配内存空间。首先我们要看下Java虚拟机中内存的布局。

对象内存分配有两种方式,指针碰撞和空闲列表,在连续的内存中通过调整指针给对象分配足够的内存,此方式需要其内存回收采用带整理的算法才能保证有足够连续的内存。而且为了应对并发分配时指针碰撞问题,需要采用本地线程分配缓冲TLAB(优先为每个线程分配一段空间,对象内存先尝试在本线程空间内分配)或者CAS+失败重试的方式。而空闲列表则是指虚拟机维护一个队列,将可用空间地址记录在列表上,对象分配时更新列表上的标记。采用哪种分配方式和GC算法绑定。

在分配时,优先从新生代的Eden区域进行分配,如果此时Eden区域可用内存小于该对象内存(对象内存在加载其class对象时已确定大小),则尝试执行minorGC以腾出空间,该GC会对新生代执行GC算法,一般新生代分为1个Eden和2个Survivor,其大小为8:1:1。该过程就是将存活的对象从Eden和Survivor from拷贝到Survivor to(对象年龄+1),如果Survicor To空间不足,则采用老年代空间担保(如果老年代空间也不足,则发起FullGC),将存活对象直接存入老年代,此时腾出的Eden区域空间来分配给新创建的ObjectA对象。此外,如果ObjectA对象如果大小超过了虚拟机设置的大对象限制值,则会在老年代分配该对象。当然进入老年代还有其他一些方式,比如动态年龄判断(相同年龄对象大小的和超过该区域大小的一半时,则该年龄以上的对象直接进入老年代)、长期存活对象(年龄大于15)。

在空间分配好了,会对对象的成员变量赋初始零值。这也是为什么成员变量不初始化能使用而方法中的局部变量不初始化不能使用的原因。

对象头信息更新

在上一步分配好对象内存空间后,需要更新对象头,对象头包含三部分

  1. Mark Word:gc年龄、偏向锁、hashcode值、元数据等
  2. 对象实例数据:对象成员变量等的数据
  3. Padding:Java中为了方便对象访问,每个对象的位置必须从8字节的倍数开始

执行构造方法

执行对象的构造方法,完成对象的创建。

相关推荐
Nyarlathotep01136 分钟前
并行设计模式(3):Future模式
java·后端
流星雨在线9 分钟前
汇总:Tomcat 安装与常用配置
java·tomcat
小冷coding31 分钟前
【面试】结合项目整理的场景面试题,覆盖 Java 基础、锁、多线程、数据库、分布式锁 / 事务、消息中间件等核心维度
java·数据库·面试
鬼先生_sir32 分钟前
SpringCloud-GateWay网关
java·spring cloud·gateway
卓怡学长1 小时前
m319个人网站的设计与实现
java·数据库·spring·tomcat·maven·intellij-idea
Zzj_tju1 小时前
Java 从入门到精通(十二):File 与 IO 流基础,为什么程序“读写文件”时总是容易出问题?
java·python·php
橘子编程2 小时前
操作系统原理:从入门到精通全解析
java·linux·开发语言·windows·计算机网络·面试
飞Link2 小时前
LangGraph 核心架构解析:节点 (Nodes) 与边 (Edges) 的工作机制及实战指南
java·开发语言·python·算法·架构
xuhaoyu_cpp_java2 小时前
Boyer-Moore 投票算法
java·经验分享·笔记·学习·算法
JavaEdge.2 小时前
Chrome加载已解压的扩展程序-清单文件缺失或不可读取 无法加载清单
java