首次来源:京东 2021 面试部门零售
说下jvm对象的创建过程
最后更新:2026-10-30 · 基于第 1 次作答
结论:对象创建 = 类加载检查 → 分配内存 → 零值初始化 → 对象头 → 构造方法,并发分配靠 TLAB/CAS。 关键词:类加载检查 · 指针碰撞 · TLAB · 对象头 · 逃逸分析 边界:栈上分配(逃逸分析+标量替换)是优化,不是所有对象都进堆。
核心考点定位:面试官想听的是 new 一条指令背后 JVM 做了什么,重点是"分配内存的并发处理"和"对象内存布局"。
机制链(≥3 环):
证据锚点:
指针碰撞:堆内存规整(Serial/ParNew 带压缩),用指针分配,指针上移。空闲列表:堆不规整(CMS),用 FreeList,分配时找足够大的块。TLAB:每个线程预分配一块 Eden 区,new 先在 TLAB 分配,避免全局锁竞争。对象头:Mark Word(哈希、分代年龄、锁状态)+ 类型指针(指向类元数据)。逃逸分析:对象不逃逸且可标量替换,则栈上分配,免堆分配与 GC。零值初始化:分配后先置默认值(int=0、引用=null),再执行构造方法。CAS + 重试:TLAB 不足时全局分配用 CAS 更新指针,失败则重试,保证原子性。符号引用:new 指令操作数指向常量池 class 引用,是类加载检查的入口。Mark Word:对象头首字,32/64 位下存哈希、GC 分代年龄、锁标志位,与锁升级联动。类元数据:类型指针指向 Klass 结构,对象可定位到类的方法、常量池。对比与权衡:
| 分配方式 | 前提 | 并发处理 | 适用 |
|---|---|---|---|
| 指针碰撞 | 堆规整 | CAS + 重试 / TLAB | Serial、ParNew |
| 空闲列表 | 堆碎片 | 需维护空闲链表 | CMS |
| 栈上分配 | 逃逸分析 + 标量替换 | 无(线程栈) | 非逃逸小对象 |
常见误区:
适用边界:大对象(超过 TLAB)直接进老年代;对象创建流程对 TLAB 满、内存不足(OOM)时的处理需单独展开。
【结论】 面试官您好,JVM 创建对象的核心流程是"类加载检查 → 分配内存 → 零值初始化 → 设置对象头 → 执行构造方法"五步,其中分配内存的并发处理是重点。
【三点】 第一,new 指令先检查常量池能否定位到类的符号引用,类未加载就先走加载、解析、初始化;类加载后对象大小才确定,才能分配内存。第二,分配内存要看堆是否规整——规整用指针碰撞(指针上移),不规整用空闲列表;而且多线程并发 new 必须保证原子性,JVM 用 TLAB(线程本地分配缓冲) 让每个线程先在 Eden 预分配一块区域,new 直接在 TLAB 分配,避免全局锁竞争,TLAB 不够再走 CAS + 失败重试。第三,内存分配后先做零值初始化(保证字段有默认值),再设置对象头(Mark Word 存哈希/分代年龄/锁状态 + 类型指针指向类元数据),最后执行构造方法。另外如果开启了逃逸分析且对象不逃逸方法外、能标量替换,对象可能直接栈上分配,不涉及堆分配和 GC。
【边界】 当然,不是所有对象都走这套堆分配——逃逸分析通过的对象会栈上分配,这是 JIT 优化;而且大对象会直接进老年代(TLAB 放不下)。这套流程在 TLAB 耗尽、堆内存不足(OOM)时还有额外的分配失败处理,如果面试官追问分配失败路径,要单独展开。
题目:说下jvm对象的创建过程
难度:medium
标签:real-interview, jvm/oom, company/京东
评分:⭐⭐⭐☆☆(3/5)
创建对象要考虑当前的情况,对象是否要跳出当前的栈。如果不需要,它当前对象是否是由开启了,当前的 JVM 是否开启了标量替换,并且当前的对象是否是只在这栈上的分配,不会涉及逃逸。如果是这样的话,它直接申请空间,把那个对象转化为对应的基础对象,基础类型的数据,而不是对象了,直接就赋值了。这时候它的分配整个直接在栈上分配,并不涉及后续的堆分配啊、堆回收之类的事。如果这个对象是一个引用对象,比如说 string 或者是一些哈希 map,这时候它会涉及申请堆空间,建立指针指向对应的堆空间。标准过程是从 new 开始,new 命令开始,然后检查类的信息是否加载到 JVM 中。如果未加载就去加载,如果已加载就开始通过类的信息去申请内存空间。判断当前的对象是要栈上分配还是要堆上分配,根据具体的引用情况去考虑。然后创建对象头,根据对象头信息去申请堆的空间。然后创建引用,把对象头的引用信息指向对应的堆空间。
优点:逃逸分析 / 标量替换 / 栈上分配是亮点;new → 类加载检查 → 分配内存 → 对象头流程清楚;区分了栈分配与堆分配。
不足:漏了TLAB / 指针碰撞 / 空闲列表(分配内存的并发处理)、零值初始化、对象头的 Mark Word 布局;流程只到"对象头",没到构造方法。
补充:标准流程"类加载检查→分配内存(TLAB/CAS)→零值→对象头→构造",对象头 Mark Word 与锁升级相关。
完整讲解见上方「完整讲解(权威版)」