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 频率,提升性能。

相关推荐
身如柳絮随风扬4 小时前
Java中的CAS机制详解
java·开发语言
-dzk-6 小时前
【代码随想录】LC 59.螺旋矩阵 II
c++·线性代数·算法·矩阵·模拟
qq_192779876 小时前
高级爬虫技巧:处理JavaScript渲染(Selenium)
jvm·数据库·python
风筝在晴天搁浅6 小时前
hot100 78.子集
java·算法
Jasmine_llq6 小时前
《P4587 [FJOI2016] 神秘数》
算法·倍增思想·稀疏表(st 表)·前缀和数组(解决静态区间和查询·st表核心实现高效预处理和查询·预处理优化(提前计算所需信息·快速io提升大规模数据读写效率
超级大只老咪6 小时前
快速进制转换
笔记·算法
u0109272716 小时前
使用Plotly创建交互式图表
jvm·数据库·python
爱学习的阿磊6 小时前
Python GUI开发:Tkinter入门教程
jvm·数据库·python
m0_706653236 小时前
C++编译期数组操作
开发语言·c++·算法
故事和你917 小时前
sdut-Java面向对象-06 继承和多态、抽象类和接口(函数题:10-18题)
java·开发语言·算法·面向对象·基础语法·继承和多态·抽象类和接口