1. 整体流程概览

当我们在 Java 中执行:

MyObject obj = new MyObject();

JVM 会经历以下几个主要步骤:

  1. 类加载检查
  2. 分配内存(堆中分配)
  3. 初始化默认值
  4. 执行构造方法
  5. 返回对象引用

2. 详细流程解析

(1) 类加载检查

  • JVM 首先检查该类是否已经被加载、解析和初始化(ClassLoader + Class 文件解析)。
  • 如果类还没有加载:
    • 通过 类加载器(ClassLoader)加载 .class 文件
    • 解析类结构(方法、字段、常量池等)
    • 初始化静态变量和静态代码块

(2) 分配内存

对象的内存分配发生在 Java 堆(Heap) 中,具体方式取决于 GC 的实现和内存布局策略:

  • 指针碰撞(Bump-the-pointer)
    如果堆是规整的(无碎片),只需将分配指针向空闲区域移动对象大小的距离即可。

  • 空闲列表(Free List)
    如果堆中有碎片,需要维护一个空闲块列表,从中找到合适的内存块分配给对象。

线程安全保障

  • TLAB(Thread Local Allocation Buffer):每个线程在新生代 Eden 区预分配一小块内存,减少锁竞争。
  • 如果 TLAB 不够用,才会使用全局堆分配,并加锁保证安全。

(3) 初始化默认值

  • JVM 会将对象的实例字段初始化为默认值:
    • 数值类型 → 0
    • boolean → false
    • 引用类型 → null
  • 这一步保证对象在构造方法执行前是可用的。

(4) 执行构造方法

  • 调用对象的构造方法(<init> 方法),执行我们在类中定义的初始化逻辑。
  • 如果父类有构造方法,会先调用父类构造方法。

(5) 返回对象引用

  • JVM 将对象的引用返回给调用方。
  • 引用存储在栈帧的局部变量表中,指向堆中的对象。

3. 内存分配与 GC 的关系

  • 新对象优先分配在新生代 Eden 区
  • 如果对象很大(超过某个阈值),可能直接分配到老年代
  • 长期存活的对象会在 GC 时晋升到老年代

4. 流程示意图

步骤 操作 说明
1 类加载检查 确认类已加载,否则加载并初始化
2 分配内存 堆中分配空间(TLAB 或全局堆)
3 初始化默认值 所有字段赋默认值
4 执行构造方法 调用 <init> 完成初始化
5 返回引用 栈中保存对象引用

总结: Java new 对象分配内存的核心过程是: 类加载 → 堆内存分配 → 默认值初始化 → 构造方法执行 → 返回引用
其中,TLAB指针碰撞 是提升分配效率的关键技术。

解答疑惑:如何判断对象很大?

1. 控制参数

-XX:PretenureSizeThreshold

  • 单位:字节(Bytes)
  • 作用:当新创建的对象大小超过该阈值时,直接在老年代分配,跳过新生代 Eden 区。
  • 默认值:0(表示禁用该功能)
  • 适用 GC:仅在 Serial 和 ParNew 收集器中生效,对 G1、CMS 等不适用。

2. 判断对象是否很大的流程

  1. 计算对象大小
    • JVM 在分配前会根据对象的字段、对象头(Mark Word + Class Pointer)、对齐填充等信息计算对象所需的字节数。
  2. 比较阈值
    • 如果对象大小 > PretenureSizeThreshold → 直接分配到老年代
    • 否则 → 按正常流程分配到新生代 Eden 区
  3. 特殊情况
    • 大数组(如 byte[]int[])是最常见的直接进入老年代的对象类型
    • 某些 GC(如 G1)会用自己的大对象判断逻辑(Region 大小相关)

3. 示例

假设我们设置:

-XX:PretenureSizeThreshold=1048576 # 1MB

那么:

byte[] bigArray = new byte[2 * 1024 * 1024]; // 2MB

这个对象会直接分配到老年代,因为它超过了 1MB 阈值。


4. 注意事项

  • 该参数只对 Serial / ParNew 有效,在 G1 中无效,因为 G1 会将大对象放到 Humongous Region。
  • 如果频繁创建大对象,可能导致老年代快速填满,引发 Full GC
  • 大对象直接进入老年代的目的是避免在新生代复制时的高成本(复制算法对大对象开销很大)。

总结
判断对象是否很大,核心就是:

对象大小 > -XX:PretenureSizeThreshold → 直接进入老年代
否则进入新生代 Eden 区。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐