JVM内存管理与垃圾回收是一体协同的运行保障机制:内存划分决定对象存储位置,垃圾回收决定其回收时机,核心目标是确保Java程序在有限内存中稳定高效长期运行。

JVM 内存管理与垃圾回收不是两个孤立模块,而是一体协同的运行保障机制:内存划分为不同区域决定对象“住哪”,垃圾回收则决定对象“何时搬走”。核心目标只有一个——让 Java 程序在有限内存中稳定、高效、自动地长期运行。
内存区域划分:各司其职,动静分明
JVM 启动时向操作系统申请一大块连续内存,再按用途切分为多个逻辑区域:
- 线程私有区(自动释放):程序计数器、虚拟机栈、本地方法栈。这些区域生命周期与线程绑定,方法调用结束或线程终止时,所占内存自然归还,无需 GC 干预。
- 线程共享区(GC 主战场):Java 堆和方法区(JDK 8+ 后为元空间)。堆存放所有 new 出的对象实例,是 GC 最频繁操作的区域;方法区存储类信息、常量、静态变量等,也会被回收(如卸载无用类)。
- 堆内进一步分代:年轻代(Eden + 两个 Survivor 区)专收“朝生夕死”的短命对象;老年代存放经多次 GC 仍存活的长期对象;元空间(替代永久代)使用本地内存,不受堆大小限制,但需防本地内存耗尽。
对象存活判定:从引用计数到可达性分析
GC 不是凭空清理,必须先准确识别哪些对象真正“已死”:
- 引用计数法因无法处理循环引用(如 A 引用 B、B 又引用 A),且维护开销大,现代 JVM 均未采用。
- 可达性分析是实际标准:以 GC Roots(如栈帧中的局部变量、静态字段、JNI 引用等)为起点,沿引用链向下搜索。任何对象若无法被任何 GC Root 到达,即被标记为可回收。
- 即使被标记,对象也未必立即消失——finalize() 方法(已废弃)曾提供一次“自救”机会,但不可靠且性能差,JDK 9 起已标记为 deprecated,不应依赖。
垃圾回收算法:按需匹配,分代施策
不同区域对象生命周期差异大,单一算法效率低,因此 JVM 采用分代收集策略:
- 年轻代用复制算法:只复制存活对象到一个 Survivor 区,清空 Eden 和另一 Survivor。适合“大量死亡、少量存活”场景,效率高、无碎片。
- 老年代用标记-整理或标记-清除:标记存活对象后,整理算法将它们向一端压缩,消除碎片;清除算法则直接回收空闲空间,但易产生碎片,可能触发 Full GC。
- 现代回收器更智能:G1 面向服务端大堆,兼顾吞吐与停顿;ZGC 和 Shenandoah 支持超大堆(TB 级)下毫秒级停顿,适用于低延迟敏感系统。
调优关键点:不靠猜,靠观察
合理配置能让 GC 从“后台干扰”变成“隐形支撑”:
- 堆大小不宜过大或过小:-Xms 和 -Xmx 设为相同值可避免动态扩容抖动;初始堆建议为物理内存的 1/4~1/2,视应用负载调整。
- 避免频繁 Full GC:检查是否因老年代过小、内存泄漏、大对象直接进入老年代(如 > -XX:PretenureSizeThreshold)引发。
- 启用 GC 日志:加参数 -Xlog:gc*:file=gc.log:time,uptime,pid,tags —— 日志里能看清每次 GC 类型、耗时、前后堆占用,是调优唯一可靠依据。
- 对象创建习惯影响深远:减少临时对象、复用对象池(谨慎评估)、及时置 null(仅对长生命周期引用有意义)比调参更根本。

















