一、基础定义
- 堆分配 默认常规创建对象方式,
new对象实例存堆,引用存在虚拟机栈。 - 栈上分配 JVM 逃逸分析优化:未逃逸对象直接分配在虚拟机栈,不在堆创建。
二、核心对比
表格
| 对比项 | 堆分配 | 栈上分配 |
|---|---|---|
| 内存位置 | JVM 堆内存 | 线程私有虚拟机栈 |
| 所属线程 | 线程共享 | 线程私有 |
| 回收方式 | 依靠 GC 垃圾回收 | 方法执行完自动出栈销毁,无 GC |
| 分配速度 | 慢 | 极快 |
| 内存大小 | 空间大 | 空间小,容量有限 |
| 触发条件 | 默认 new 对象就是堆分配 | 开启逃逸分析 + 对象不逃逸 |
| 线程安全 | 多线程可共享对象 | 仅当前方法使用,无共享 |
| 内存溢出风险 | 易 OOM | 几乎不会 |
| 是否产生 GC | 大量产生 GC | 零 GC |
三、使用场景
堆分配
- 对象要返回出去
- 赋值给成员变量、静态变量
- 多线程共享对象
- 全局长期存活对象
栈上分配
- 对象只在当前方法内使用
- 方法内临时对象,用完即弃
- 循环内大量创建局部临时对象(优化最强)
四、生命周期区别
- 堆分配:对象创建后,直到没有引用指向,才会被 GC 回收,存活时间不可控
- 栈上分配 :方法结束立刻销毁,生命周期和方法一致
五、性能差距
- 堆分配:创建对象→分配堆内存→GC 扫描回收,开销大
- 栈上分配:栈内存直接开辟,方法结束自动释放,性能提升明显
- 搭配标量替换:连对象都不创建,直接拆成基本变量,性能拉满
六、面试极简背诵
- 堆分配在共享堆内存,靠 GC 回收;栈分配在线程栈,方法结束自动释放。
- 堆分配通用,栈分配依赖逃逸分析 + 对象不逃逸。
- 栈上分配无 GC 开销,适合局部临时对象;需要对外暴露对象只能堆分配。
七、一句话总结
临时自用走栈上,对外暴露放堆里。