Java 内存分配与回收策略

一、内存分配策略

Java 对象的内存分配主要发生在堆内存(新生代、老年代),少数情况可能分配在栈(栈上分配)或直接内存(堆外内存)。核心分配策略包括:

  1. 优先分配到新生代 Eden 区 绝大多数新创建的对象首先分配在新生代的 Eden 区。当 Eden 区空间不足时,触发 Minor GC,存活对象会被移至 Survivor 区(From 区)。

  2. 大对象直接进入老年代 大对象(如长字符串、大数组)会直接分配到老年代,避免在新生代频繁复制(可通过 -XX:PretenureSizeThreshold 配置阈值)。

  3. 长期存活对象进入老年代 每个对象有年龄计数器,每经历一次 Minor GC 存活则年龄 + 1,当年龄达到阈值(默认 15,-XX:MaxTenuringThreshold)时进入老年代。

  4. 动态年龄判定Survivor 区中相同年龄的对象总和超过 Survivor 空间的一半时,年龄≥该年龄的对象直接进入老年代(无需等到阈值)。

  5. 空间分配担保Minor GC 前,JVM 检查老年代最大可用连续空间是否大于新生代所有对象总大小:

    • 若成立,Minor GC 安全;
    • 若不成立但开启 -XX:-HandlePromotionFailure,检查老年代可用空间是否大于历次晋升老年代的平均大小,若成立则尝试 Minor GC(有风险),否则触发 Full GC。
  6. 栈上分配(逃逸分析) 通过逃逸分析,若对象未逃逸出方法,则直接分配在栈上,无需进入堆,减少 GC 压力(需开启 -XX:+DoEscapeAnalysis)。

  7. 标量替换 对未逃逸的对象,将其拆解为基本类型变量分配在栈上(需开启 -XX:+EliminateAllocations)。

二、垃圾回收(GC)策略

GC 的核心是回收堆中不再被引用的对象,根据回收区域分为:

1. Minor GC(新生代 GC)
  • 触发条件:Eden 区空间不足时触发。
  • 回收区域:新生代(Eden + Survivor)。
  • 回收算法:复制算法(效率高,新生代对象存活率低)。
  • 过程:将 Eden 和 From Survivor 存活对象复制到 To Survivor,清空 Eden 和 From Survivor,然后交换 From/To Survivor 角色。
  • 特点:频率高、速度快,暂停时间短。
2. Major GC / Full GC(老年代 GC)
  • Major GC :仅回收老年代的 GC(多与 Minor GC 并发发生);Full GC:回收新生代 + 老年代 + 元空间的 GC(Stop-The-World 时间长)。

  • 触发条件

    • 老年代空间不足(如大对象分配失败、Minor GC 后晋升老年代的对象超过老年代剩余空间);
    • 元空间(Metaspace)不足(永久代时代为永久代满);
    • 调用 System.gc()(建议性,JVM 可能忽略);
    • CMS GC 时出现 "Concurrent Mode Failure"(并发回收时老年代空间不足);
    • 空间分配担保失败。
  • 回收算法:老年代多采用标记 - 清除 / 标记 - 整理算法(对象存活率高,复制算法效率低)。

  • 特点:频率低、速度慢,暂停时间长(CMS 等并发 GC 可减少暂停)。

三、常见垃圾收集器的回收策略
  1. Serial GC:新生代 Serial(复制)+ 老年代 Serial Old(标记 - 整理),单线程,适合单核心场景。
  2. ParNew GC:新生代并行版(多线程复制)+ 老年代 Serial Old,配合 CMS 使用。
  3. Parallel Scavenge:新生代并行复制,关注吞吐量(吞吐量 = 用户时间 /(用户时间 + GC 时间)),老年代 Parallel Old(标记 - 整理)。
  4. CMS(Concurrent Mark Sweep):老年代并发标记 - 清除,低延迟,分初始标记、并发标记、重新标记、并发清除阶段(会产生内存碎片)。
  5. G1(Garbage-First):分区堆内存,混合回收新生代和老年代,兼顾吞吐量和延迟,优先回收垃圾多的区域。

总结

  • 内存分配:优先 Eden 区,大对象 / 长期对象进老年代,栈上分配优化。
  • Minor GC:新生代高频回收,速度快;
  • Full GC:回收全堆,成本高,需尽量避免(如优化对象生命周期、调整 JVM 参数)。

合理配置新生代 / 老年代比例(如 -XX:NewRatio)、GC 算法和阈值,可有效减少 Full GC 频率,提升性能。

相关推荐
せいしゅん青春之我1 小时前
【JavaEE进阶】JVM-面试中的高频考点1
java·网络·jvm·笔记·面试·java-ee
陈逸轩*^_^*1 小时前
深入理解 Java JVM,包括垃圾收集器原理、垃圾回收算法原理、类加载机制等
java·jvm
2***57421 小时前
Java内存泄漏排查工具
java·开发语言
S***H2832 小时前
Java在微服务网关中的实现
java·开发语言·微服务
cherry有点甜·2 小时前
标题调用外部接口apifox与浏览器显示不一致
java
家有两宝,感恩遇见2 小时前
不能明文传证件号码后端加密解密最简单的方式AES
java·服务器·开发语言
90后小陈老师2 小时前
用户管理系统 04 实现后端登录功能 | Java新手实战 | 最小架构 | 期末实训 | Java+SpringBoot+Vue3
java·spring boot·架构
做怪小疯子2 小时前
LeetCode 热题 100——普通数组——除自身以外数组的乘积
数据结构·算法·leetcode
❀͜͡傀儡师2 小时前
springboot集成mqtt服务,自主下发
java·spring boot·后端·mqtt·netty