news 2026/1/26 13:30:45

Java 中 new 一个对象的过程是怎么样的?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 中 new 一个对象的过程是怎么样的?

Java 中new 一个对象的过程是从字节码解析到内存分配、初始化、引用返回的完整链路,涉及 JVM 类加载、内存管理、构造方法执行等核心机制。以下按「JVM 层面的核心步骤」+「代码层面的直观拆解」展开,兼顾底层原理和实际理解:

一、核心前提:类必须先加载(首次创建对象时)

如果该类从未被 JVM 加载过,执行new前会先触发类加载流程(加载→验证→准备→解析→初始化),确保类的元数据(如字段、方法、常量池)被加载到方法区(JDK 1.8+ 为元空间)。

  • 加载:通过类的全限定名读取字节码文件(.class);
  • 初始化:执行静态代码块(<clinit>)、静态变量赋值(如static int a = 10);
  • 注意:类加载仅执行一次,后续创建该类对象时跳过此步骤。

二、new 对象的核心步骤(JVM 层面)

User user = new User("张三", 20);为例,完整流程如下:

步骤1:检查类加载状态 + 分配内存

JVM 先确认User类已加载,然后为新对象分配堆内存

  • 内存大小确定:根据类的元数据(字段类型、数量)计算对象所需内存(如对象头 + 实例字段 + 对齐填充);
  • 内存分配方式
    • 「指针碰撞」:堆内存规整(Serial/ParNew 收集器),JVM 移动空闲指针,划分出对象所需内存;
    • 「空闲列表」:堆内存碎片化(CMS 收集器),JVM 从空闲列表中找到足够大的内存块分配;
  • 线程安全保障
    • 方案1:CAS + 失败重试(保证分配原子性);
    • 方案2:TLAB(本地线程分配缓冲)—— 每个线程在堆中预留一小块内存,优先在 TLAB 分配,避免竞争(默认开启)。
步骤2:内存初始化(零值填充)

分配完内存后,JVM 会将对象的实例字段初始化为对应类型的零值(不执行赋值语句,仅清空内存):

  • 例如:Username字段(String 类型)被设为nullage字段(int 类型)被设为0,引用类型默认null,基本类型默认对应零值(boolean→false,long→0L 等);
  • 目的:保证对象字段在构造方法执行前,不会出现“未初始化的脏数据”。
步骤3:设置对象头(Object Header)

在分配的内存中设置对象头信息,包含:

  • Mark Word:存储对象的哈希值、GC 分代年龄、锁状态、偏向锁线程 ID 等;
  • 类型指针:指向对象所属类的元数据(如User.class),JVM 通过该指针确认对象的类型;
  • (数组对象额外)数组长度:若为数组对象,还会存储数组长度字段。
步骤4:执行实例初始化方法(<init>

这是「代码层面感知最明显」的步骤,JVM 调用对象的构造方法(<init>是编译器生成的初始化方法,对应代码中的构造函数):

  • 执行顺序:
    1. 先调用父类的<init>方法(隐式super(),若未显式调用,编译器自动添加),递归直到Object类;
    2. 执行实例变量的显式赋值(如private String name = "默认名");
    3. 执行构造方法中的自定义逻辑(如this.name = name; this.age = age;);
  • 关键:<init>方法是对象初始化的核心,只有执行完<init>,对象才是“完整可用”的
步骤5:返回对象引用

JVM 将堆中对象的内存地址赋值给栈中的引用变量(如user):

  • 注意:引用变量(user)存储在栈帧的局部变量表中,指向堆中的实际对象;
  • 特殊情况:JIT 优化可能将对象“标量替换”到栈上(逃逸分析),避免堆内存分配(如局部对象未逃逸出方法)。

三、代码层面的直观拆解(结合示例)

以自定义User类为例,直观对应上述步骤:

classUser{// 实例字段privateStringname;privateintage;// 静态代码块(类加载时执行,仅一次)static{System.out.println("User类初始化(静态代码块)");}// 构造方法publicUser(Stringname,intage){this.name=name;this.age=age;System.out.println("构造方法执行:初始化name和age");}}// 创建对象publicclassTest{publicstaticvoidmain(String[]args){Useruser=newUser("张三",20);}}
执行输出(首次创建):
User类初始化(静态代码块) 构造方法执行:初始化name和age
对应步骤:
  1. 首次执行new User()→ 触发User类加载,执行静态代码块;
  2. JVM 为User对象分配堆内存;
  3. 内存零值填充:name=nullage=0
  4. 设置对象头(Mark Word + 指向User.class的类型指针);
  5. 执行<init>方法:
    • 调用Object<init>(隐式);
    • 执行构造方法逻辑,将name设为“张三”,age设为 20;
  6. 将堆中对象地址赋值给栈中的user引用。

四、关键补充:易混淆的细节

1.newvsclonevs 反射创建对象
  • new:触发类加载 + 完整的<init>执行;
  • clone:不执行构造方法,直接拷贝已有对象的内存(浅拷贝);
  • 反射(Class.newInstance()/Constructor.newInstance()):触发<init>,但可绕过访问权限(如私有构造)。
2. 逃逸分析对new的影响

若对象未逃逸出方法(如仅在方法内使用),JIT 会优化为「栈上分配」,无需在堆中创建,减少 GC 压力:

publicstaticvoidtest(){// 对象仅在方法内使用,逃逸分析后栈上分配Useru=newUser("李四",25);}
3. 构造方法的本质

构造方法不是“创建对象”,而是“初始化对象”—— 对象的内存分配在构造方法执行前已完成,构造方法仅负责给字段赋值。

五、总结:new 对象的核心链路

类加载(首次) → 分配堆内存 → 零值填充 → 设置对象头 → 执行<init>(父类构造+实例赋值+自定义逻辑) → 返回对象引用
  • 核心:JVM 先完成“内存层面的对象创建”,再通过构造方法完成“业务层面的初始化”;
  • 关键:只有执行完<init>,对象才是合法可用的,否则可能出现字段未初始化的异常。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/24 19:45:29

【辐射源分选】原型校准域自适应射频指纹识别【附python代码】

文章来源&#xff1a;微信公众号&#xff1a;EW Frontier 原型校准域自适应射频指纹识别 题目 基于原型校准的开集域自适应射频指纹识别 摘要 作为无线物联网&#xff08;IoT&#xff09;设备的基础安全机制&#xff0c;射频指纹识别&#xff08;RFFI&#xff09;在开放环境…

作者头像 李华
网站建设 2026/1/24 21:42:12

AI历史与发展-AI历史给我们的启示

第五章&#xff1a;AI历史给我们的启示 5.1 技术发展的规律 5.1.1 从寒冬到春天&#xff1a;技术发展的周期性 历史规律&#xff1a; 过度承诺 → 资金投入 → 技术瓶颈 → 寒冬 → 新突破 → 春天实际例子&#xff1a; 第一次AI寒冬&#xff08;1970s&#xff09;&#xf…

作者头像 李华
网站建设 2026/1/24 20:16:40

DCFrame终极指南:用Swift构建复杂iOS界面的完整实战教程

DCFrame终极指南&#xff1a;用Swift构建复杂iOS界面的完整实战教程 【免费下载链接】DCFrame DCFrame is a Swift UI collection framework, which can easily create complex UI. 项目地址: https://gitcode.com/gh_mirrors/dc/DCFrame 还在为iOS复杂UI布局编写数百行…

作者头像 李华
网站建设 2026/1/25 0:07:11

PHP “真异步“ TrueAsync SAPI 与 NGINX Unit 集成

八年前&#xff0c;甚至更早的时候&#xff0c;模块加载、组件打包、脚本解释、数据库查询——这些步骤慢一点&#xff0c;对业务和用户也不会造成太大影响。现在不一样了。Web 开发的核心已经变成了最大化服务器响应速度。这种转变来自网速的提升和单页应用&#xff08;SPA&am…

作者头像 李华
网站建设 2026/1/25 5:03:41

终极指南:5步搞定移动应用内存泄漏检测

终极指南&#xff1a;5步搞定移动应用内存泄漏检测 【免费下载链接】KOOM KOOM is an OOM killer on mobile platform by Kwai. 项目地址: https://gitcode.com/gh_mirrors/ko/KOOM 在移动应用开发中&#xff0c;内存管理一直是困扰开发者的核心难题。随着业务逻辑的复杂…

作者头像 李华