Skip to content

Java堆(Heap)

一、基础定义

  1. 线程共享:JVM中唯一一块所有线程共享的运行时内存区域;
  2. 存储内容:所有Java对象实例、数组全部在堆中分配;
  3. OOM风险:堆内存空间耗尽且无法扩容时,抛出 java.lang.OutOfMemoryError: Java heap space
  4. GC核心区域:垃圾回收器主要管理的内存区域。

二、堆内存分区结构

堆分为两大块:年轻代(Young Generation) + 老年代(Old Generation)

1. 年轻代 Young

比例默认 Eden : S0 : S1 = 8 : 1 : 1

  • Eden区:绝大多数新创建对象的存放位置;Eden占年轻代80%;
  • Survivor0(S0)、Survivor1(S1):两块大小完全相等的存活区,同一时间只有一块处于使用状态。 对象流转规则:
  1. 新建对象放入Eden;
  2. Eden满触发Minor GC,存活对象复制到空闲Survivor;
  3. 反复GC后对象年龄到达阈值(默认15),晋升到老年代。

2. 老年代 Old

存放长期存活、生命周期长的对象:

  1. 多次Minor GC后存活、年龄达标晋升的对象;
  2. 大对象(超大数组/实例)直接分配到老年代,避免大量复制开销; 老年代空间不足触发Full GC,回收整个堆内存。

三、JDK7 与 JDK8 方法区(永久代/元空间)核心区别

JDK7:永久代 PermGen

  1. 位置:堆内存内部,属于堆的一部分;
  2. 存储:类元信息、静态变量、常量池、字节码;
  3. 缺陷:永久代固定大小,大量动态加载类极易发生永久代OOM。

JDK8:元空间 Metaspace

  1. 位置:移至操作系统本地内存(堆外),不再占用堆空间;
  2. 存储:原永久代全部数据迁移至元空间;
  3. 优势:默认无固定上限,受操作系统物理内存限制,大幅减少类加载导致的OOM。

四、完整总结(面试背诵版)

  1. Java堆是线程共享内存,存放全部对象与数组,内存耗尽抛出堆OOM;
  2. 堆分为年轻代、老年代:年轻代Eden+两个等量Survivor,存放新生短期对象;老年代存放长期存活老对象;
  3. JDK7存在堆内永久代,易类加载OOM;JDK8移除永久代,改用堆外本地内存元空间,规避永久代溢出问题。

五、面试简答

问:详细介绍Java堆?

答: 堆是JVM线程共享的内存区域,所有对象实例、数组都在堆分配,堆空间不足会抛出堆内存OOM。 堆分为年轻代和老年代:年轻代分为Eden、S0、S1三块,比例8:1:1,新对象先放Eden,Minor GC存活对象进入Survivor,年龄达标后晋升老年代;老年代存放生命周期长的对象。 JDK7堆内有永久代存储类信息,容易OOM;JDK8把永久代移除,改为操作系统本地内存的元空间,解决类加载溢出问题。

Powered by VitePress 1.6.4 | 持续更新中