MST

星途 面试题库

面试题:Java垃圾回收调优中的内存分配与回收策略

在Java垃圾回收调优过程中,内存分配与回收策略是至关重要的。请详细阐述对象在新生代和老年代的分配规则,以及不同垃圾回收器如何依据这些规则进行优化。
27.1万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

对象在新生代和老年代的分配规则

  1. 新生代分配规则
    • 大多数新创建的对象:Java中,新创建的对象通常首先分配在新生代的Eden区。例如,当执行Object obj = new Object();时,obj对象会优先在Eden区分配内存。
    • Eden区满时:当Eden区的空间被占满,会触发Minor GC(新生代垃圾回收)。此时,Eden区和From Survivor区中存活的对象会被复制到To Survivor区,而未被引用的对象则被回收。From Survivor区和To Survivor区是新生代中的两个Survivor区,它们的角色在每次垃圾回收后会互换。
    • 对象晋升:对象每经历一次Minor GC且存活,年龄(对象头中记录对象经历GC次数的字段)就会加1。当对象的年龄达到一定阈值(默认是15,可通过-XX:MaxTenuringThreshold参数调整),该对象会被晋升到老年代。例如,一个对象在新生代经过15次Minor GC后仍然存活,就会被移动到老年代。
  2. 老年代分配规则
    • 大对象直接进入老年代:所谓大对象,是指需要大量连续内存空间的对象,比如很长的数组。通过-XX:PretenureSizeThreshold参数可以设置大对象的大小,超过此大小的对象直接在老年代分配内存,避免在新生代中因频繁复制而影响性能。例如,如果设置-XX:PretenureSizeThreshold = 1024 * 1024(即1MB),那么大于1MB的对象会直接在老年代分配。
    • 长期存活的对象:如上述提到,当对象在新生代经历多次Minor GC且年龄达到晋升阈值时,会晋升到老年代。

不同垃圾回收器依据这些规则的优化

  1. Serial垃圾回收器
    • 新生代:Serial垃圾回收器在新生代采用复制算法。在Minor GC时,它会暂停所有应用线程,将Eden区和From Survivor区中存活的对象复制到To Survivor区。由于是单线程回收,它适用于单核环境,且在回收过程中应用程序处于停顿状态。它会严格按照对象在新生代的分配和晋升规则进行操作,确保对象在不同区域间合理移动。
    • 老年代:在老年代采用标记 - 压缩算法。在Full GC(针对老年代和新生代的垃圾回收)时,同样暂停应用线程,先标记出老年代中存活的对象,然后将存活对象压缩到内存一端,清理掉另一端的空间。它根据对象在老年代的分配规则,处理大对象和晋升对象的内存管理。
  2. Parallel Scavenge垃圾回收器
    • 新生代:Parallel Scavenge垃圾回收器在新生代也采用复制算法,但它是多线程的。多个线程同时进行垃圾回收,能有效缩短垃圾回收时间。它以吞吐量为优先目标,通过调整新生代的大小、对象晋升阈值等参数,来优化垃圾回收过程,使应用程序在运行过程中尽可能少地被垃圾回收打断,从而提高整体吞吐量。它同样遵循对象在新生代的分配和晋升规则。
    • 老年代:Parallel Scavenge垃圾回收器通常搭配Parallel Old垃圾回收器来处理老年代。Parallel Old垃圾回收器在老年代采用多线程的标记 - 压缩算法。在Full GC时,多线程并行标记和压缩老年代中的存活对象,提高老年代垃圾回收的效率,并且按照老年代对象分配规则管理内存。
  3. CMS(Concurrent Mark Sweep)垃圾回收器
    • 新生代:CMS垃圾回收器在新生代一般搭配ParNew垃圾回收器(它是Serial垃圾回收器的多线程版本)。ParNew垃圾回收器在新生代采用多线程的复制算法进行Minor GC,遵循新生代对象分配和晋升规则。
    • 老年代:CMS垃圾回收器在老年代采用标记 - 清除算法。它的目标是尽量减少垃圾回收时应用程序的停顿时间。在垃圾回收过程中,它分为初始标记(STW,停顿所有应用线程,标记出与GC Roots直接相连的对象)、并发标记(与应用程序并发执行,标记出所有存活对象)、重新标记(STW,修正并发标记期间因应用程序运行导致标记变动的部分)和并发清除(与应用程序并发执行,清除未标记的对象)几个阶段。它根据老年代对象分配规则管理大对象和晋升对象,但标记 - 清除算法可能会产生内存碎片问题。
  4. G1(Garbage - First)垃圾回收器
    • 整体区域划分:G1垃圾回收器将堆内存划分为多个大小相等的Region,这些Region既可以属于新生代,也可以属于老年代。
    • 新生代:G1垃圾回收器在新生代采用复制算法。它通过动态调整新生代的Region数量来管理内存。在进行新生代垃圾回收(Mixed GC)时,它会根据垃圾回收的收益(回收的垃圾数量)和成本(暂停时间),选择部分Region进行回收,遵循对象在新生代的分配和晋升规则。
    • 老年代:在老年代,G1同样采用复制算法。当老年代空间占用达到一定阈值(可通过-XX:InitiatingHeapOccupancyPercent参数设置,默认45%),会触发混合回收,回收一部分新生代Region和老年代Region。G1会根据对象在老年代的分配规则,处理大对象和晋升对象,并通过整理Region来减少内存碎片。