JVM原理之完整的一次GC流程

本文详细介绍JVM垃圾回收机制,包括可达性分析算法、堆内存结构及其分区、新生代与老年代对象的分配和回收策略,以及一次完整的GC流程。帮助理解如何优化JVM性能。

JVM 的 GC 是指垃圾回收,主要是对堆内存的回收。本文将介绍 JVM 中一次完整的 GC 流程是怎样的,首先抛出第一个问题,什么样的对象会是 JVM 回收的目标?

一、可达性分析算法(GC Roots)

有一种引用计数法,可以用来判断对象被引用的次数,如果引用次数为0,则代表可以被回收。

这种实现方式比较简单,但对于循环引用的情况束手无策,所以 Java 采用了可达性分析算法

即判断某个对象是否与 GC Roots 的这类对象之间的路径可达,若不可达,则有可能成为回收对象,被判定为不可达的对象要成为可回收对象必须至少经历两次标记过程,如果在这两次标记过程中仍然没有逃脱成为可回收对象的可能性,则基本上就真的成为可回收对象了。

在 Java 中,可作为 GC Roots 的对象包括以下几种:

  1. 虚拟机栈(本地变量表)中引用的对象
  2. 方法区中类静态属性引用的对象
  3. 方法区中常量引用的对象
  4. 本地方法栈中引用的对象

二、JVM中的堆结构

JVM 中的堆可划分为两大部分,新生代和老年代,大小比例为1:2,如下:

其中,新生代分为 Eden 区和 Survivor 区, Survivor 幸存者区又分为大小相等的两块 from 和 to 区。这便是 JVM 中堆的结构和各部分默认的比例,当然这些比例都可通过对应 JVM 参数来调整。

2.1 为何新生代要分为三个区

这里需要介绍新生代的垃圾回收算法——复制算法。该算法的核心是将可用内存按容量划分为大小相等的两块,每次回收周期只用其中一块,当这一块的内存用完,就将还存活的对象复制到另一块上面,然后把已使用过的内存空间清理掉。

  • 优点:不必考虑内存碎片问题;效率高。
  • 缺点:可用容量减少为原来的一半,比较浪费。

【最优设置】:根据权威数据分析,90%的对象都是朝生夕死的,所以采用10%的空间用作交换区,因为交换区必须要有等量的两个,所以采用复制算法中新生代中三个区默认分配比例为8:1:1。

2.2 新生代对象的分配和回收

(1)基本上新的对象优先在 Eden 区分配;

(2)当 Eden 区没有足够空间时,会发起一次 Minor GC

(3)Minor GC 回收新生代采用复制回收算法的改进版本,即

  • from 区和 to 区的两个交换区,这两个区只有一个区有数据
  • 采用8:1:1的默认分配比例(**-XX:SurvivorRatio**默认为8,代表 Eden 区与 Survivor 区的大小比例)

2.3 老年代对象的分配和回收

(1)老年代的对象一般来自于新生代中的长期存活对象。这里有一概念叫做年龄阈值,每个对象定义了年龄计数器,经过一次 Minor GC (在交换区)后年龄加1,对象年龄达到_15次后将会晋升到老年代,老年代空间不够时进行 Full GC。当然这个参数仍是可以通过 JVM 参数(-XX:MaxTenuringThreshold_,默认15)来调整。

(2)大对象直接进入老年代。即超过 Eden 区空间,或超过一个参数值(-XX:PretenureSizeThreshold=30m,无默认值)。这样做的目的是避免在Eden区及两个Survivor区之间发生大量的内存复制。

(3)对象提前晋升到老年代(组团)。动态年龄判定:如果在 Survivor 区中相同年龄所有对象大小总和大于 Survivor 区大小的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,而无须等到自己的晋升年龄。

三、JVM完整的GC流程

对象的正常流程:Eden 区 -> Survivor 区 -> 老年代

新生代GC:Minor GC;老年代GC:Full GC,比 Minor GC 慢10倍。

【总结】:内存区域不够用了,就会引发GC,JVM 会“stop the world”,严重影响性能。Minor GC 避免不了,Full GC 尽量避免。

【处理方式】:保存堆栈快照日志、分析内存泄漏、调整内存设置控制垃圾回收频率,选择合适的垃圾回收器等。

<think>我们需要解释GC Root可达性分析算法的原理。根据用户提供的引用内容,算法是通过GC Roots作为起点,通过引用链遍历,判断对象是否可达。如果不可达,则对象可被回收。 关键点: 1. GC Roots是什么:一组特殊的对象引用,作为起始点。 2. 可达性分析过程:从GC Roots开始,沿着引用链搜索,所有能被访问到的对象都是存活的,而无法被访问到的对象则被认为是不可达的,即可以被回收。 3. 引用链(Reference Chain):从GC Roots到某个对象的引用路径。 另外,注意引用中提到的:GC Roots包括虚拟机栈中的本地变量、方法区中的静态变量、JNI引用、活跃线程对象、系统类加载器加载的类等。 我们可以用图论的概念来类比:将对象视为节点,引用视为边,那么从GC Roots节点集合出发,能够遍历到的节点都是存活的,而遍历不到的节点就是需要回收的。 为了更清晰,我们可以用一个图示(mermaid)来展示,并配合文字说明。 同时,根据用户要求,我们要生成相关问题。 注意:用户要求使用中文,数学公式用$...$,独立公式用$$...$$,并且正确使用LaTeX。不过在这个问题中,可能涉及数学表达式较少,但如果有图论相关,我们可以用集合表示。 例如,用集合论描述: 设$G=(V, E)$是一个有向图,其中$V$是节点(对象)集合,$E$是边(引用)集合。 给定一个根节点集合$R \subseteq V$(即GC Roots),则可达节点集合为: $$Reachable = \{ v \in V \mid \text{存在一条从某个}r \in R\text{到}v\text{的路径} \}$$ 不可达节点集合为$V - Reachable$,这些节点就是可回收的。 但是注意,用户引用的内容中并没有使用数学公式,所以我们可以用文字和图示结合。 另外,注意用户要求:引用段落末尾自然地添加引用标识。 由于我们之前的回答已经解释了GC Root的定义和类型,这次重点在原理。 结构建议: 1. 算法基本思想(文字描述) 2. 算法步骤(分点) 3. 图示说明(用mermaid) 4. 算法特点 5. 相关问题 </think>### GC Root 可达性分析算法原理详解 #### 一、核心思想 可达性分析算法通过**根对象集合(GC Roots)** 作为起点,采用**图遍历**的方式判定对象存活状态。核心逻辑为: - 所有能被 GC Roots 直接或间接引用的对象 → **存活** - 所有无法通过引用链连接到 GC Roots 的对象 → **可回收垃圾** 用集合论可表示为: $$ \text{存活对象} = \{ o \mid \exists \text{路径 } \text{GC Root} \xrightarrow{\text{*}} o \} $$ #### 二、算法执行流程 1. **初始化根集合** 扫描并标记所有 GC Root 对象(虚拟机栈变量、静态变量、活跃线程等)[^1][^4]。 2. **广度优先遍历引用链** ```mermaid graph LR A[GC Root 1] --> B[对象A] A --> C[对象B] C --> D[对象C] E[GC Root 2] --> F[对象D] G[对象E] --> H[对象F] ``` - 从 GC Roots 出发,递归遍历所有引用关系 - 标记所有访问到的对象为**可达**(例如上图中 A→F 对象) 3. **判定不可达对象** 未标记的对象即为不可达对象(如对象 E→F),满足回收条件: $$ \text{可回收对象} = \text{堆中所有对象} - \text{可达对象集} $$ #### 三、算法特性 1. **准确性保证** 通过完整引用链扫描,避免循环引用误判(区别于引用计数法)[^3]。 2. **安全点机制** 遍历过程在 JVM 的安全点(Safepoint)暂停用户线程,确保对象引用状态冻结[^2]。 3. **三色标记优化** 现代 JVM 采用并发标记优化: ```mermaid flowchart LR 白[白色:未访问] --标记中--> 灰[灰色:部分访问] --完成访问--> 黑[黑色:完全访问] ``` - **白色对象**:待回收 - **灰色对象**:遍历中状态 - **黑色对象**:确认存活 #### 四、数学本质 可达性分析本质是**有向图连通性判定**: - 对象集合:$ V = \{v_1, v_2, ..., v_n\} $ - 引用关系:$ E = \{ (v_i, v_j) \mid v_i \text{ 引用 } v_j \} $ - 可达性条件:$ \forall v \in V,\ \text{reachable}(v) \iff \exists \text{路径 } \text{root} \leadsto v $ > 💡 **关键优势**:仅需 $O(n)$ 时间即可完成全堆扫描($n$ 为对象数量)[^3][^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值