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字节的倍数开始

执行构造方法

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

相关推荐
.生产的驴24 分钟前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
猿周LV31 分钟前
JMeter 安装及使用 [软件测试工具]
java·测试工具·jmeter·单元测试·压力测试
晨集33 分钟前
Uni-App 多端电子合同开源项目介绍
java·spring boot·uni-app·电子合同
时间之城36 分钟前
笔记:记一次使用EasyExcel重写convertToExcelData方法无法读取@ExcelDictFormat注解的问题(已解决)
java·spring boot·笔记·spring·excel
椰羊~王小美43 分钟前
LeetCode -- Flora -- edit 2025-04-25
java·开发语言
凯酱1 小时前
MyBatis-Plus分页插件的使用
java·tomcat·mybatis
程序员总部1 小时前
如何在IDEA中高效使用Test注解进行单元测试?
java·单元测试·intellij-idea
oioihoii1 小时前
C++23中if consteval / if not consteval (P1938R3) 详解
java·数据库·c++23
佳腾_1 小时前
【Web应用服务器_Tomcat】一、Tomcat基础与核心功能详解
java·前端·中间件·tomcat·web应用服务器
异常君2 小时前
线程池隐患解析:为何阿里巴巴拒绝 Executors
java·后端·代码规范