Java 入门指南:JVM(Java虚拟机)垃圾回收机制 —— 内存分配和回收规则

news2024/12/24 20:45:18

文章目录

    • 垃圾回收机制
    • 堆空间的基本结构
    • 内存分配和回收规则
      • 对象优先在 Eden 区分配
        • 分配担保机制
      • 大对象直接进入老年代
      • 长期存活的对象进入老年代
      • 主要进行 GC 的区域
        • 部分收集 (Partial GC):
          • Minor GC
          • Major/Old GC
          • Mixed GC
        • 整堆收集(Full GC)
      • 空间分配担保

垃圾回收机制

垃圾回收Garbage Collection,GC),顾名思义就是释放垃圾占用的空间,当需要排查各种内存溢出问题、当垃圾收集成为系统达到更高并发的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节。有效的使用可以使用的内存,对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收。

堆空间的基本结构

Java 的自动内存管理主要是针对对象内存的回收和对象内存的分配。同时,Java 自动内存管理最核心的功能是 内存中对象的分配与回收。

Java 堆是垃圾收集器管理的主要区域,也被称作 GC 堆(Garbage Collected Heap)

从垃圾回收的角度来说,由于现在收集器基本都采用分代垃圾收集算法,所以 Java 堆被划分为了几个不同的区域,这样我们就可以根据各个区域的特点选择合适的垃圾收集算法。

在 JDK 7 版本及 JDK 7 版本之前,堆内存被通常分为下面三部分:

  1. 新生代内存(Young Generation)
  2. 老生代(Old Generation)
  3. 永久代(Permanent Generation)

下图所示的 Eden 区、两个 SurvivorS0S1 都属于新生代,中间一层属于老年代,最下面一层属于永久代。

![[Pasted image 20231007094506.png]]

图片来源:JavaGuide

JDK 8 版本之后 PermGen(永久代) 已被 Metaspace(元空间) 取代,元空间使用的是本地内存。

大部分情况,对象都会首先在 Eden 区域分配,在一次新生代垃圾回收后,如果对象还存活,则会进入 S0 或者 S1,并且对象的年龄还会加 1(Eden 区->Survivor 区后对象的初始年龄变为 1)。当它的年龄增加到一定程度(默认为 15 岁),就会被晋升到老年代中。

关于 Java 堆相关知识的详细讲解,请看:JVM(Java虚拟机)—— Java 内存运行时的数据区域

内存分配和回收规则

对象优先在 Eden 区分配

大多数情况下,对象在新生代中 Eden 区分配。当 Eden 区没有足够空间进行分配时,虚拟机将发起一次 Minor GC

Eden 区没有足够空间进行分配时,虚拟机将发起一次 Minor GC(Minor Garbage Collection)。GC 期间虚拟机又发现 allocation1 无法存入 Survivor 空间,所以只好通过 JVM 内存管理技术的分配担保机制把新生代的对象提前转移到老年代中去,老年代上的空间足够存放 allocation1,所以不会出现 Full GC。执行 Minor GC 后,后面分配的对象如果能够存在 Eden 区的话,还是会在 Eden 区分配内存。

分配担保机制

分配担保机制(Allocation Assurance Mechanism) 是Java虚拟机(JVM)中的一项内存管理技术,用于确保对象在分配内存时能够被成功分配到新生代的Eden空间中,以避免在发生垃圾收集时频繁进行老年代的扩容

在新生代的内存管理中,JVM将堆空间划分为多个区域,其中包括一个 Eden 空间和两个 Survivor 空间(一般为 From(S0)To(S1))。新创建的对象会被分配到 Eden 空间中。

在进行垃圾收集时,JVM会对 Eden 空间中的存活对象进行标记和复制操作。如果 Eden 空间的可用空间不足以容纳存活的对象,就会触发一次垃圾收集。

但是,如果Eden空间中的对象有一部分存活并且无法放入Survivor空间To(S1)From(S0) 区),则通过分配担保机制将这些对象直接晋升到老年代

分配担保机制的原理是,当发生一次新生代垃圾回收时,如果发现Eden空间中的存活对象占用的空间超过了 From(S0)To(S1) 空间的可用空间之和,那么就会直接晋升这些存活对象到老年代。这样可以避免频繁进行老年代的扩容,减少了垃圾收集的次数,提高了性能。

需要注意的是,分配担保机制适用于大部分情况下,但在某些特殊情况下(如大对象或长期存活的对象),由于对象的特殊性,可能无法遵循分配担保机制的规则。这种情况下,可能会触发 Full GC(Full Garbage Collection) 进行整体的堆内存回收。

分配担保机制,用于确保对象在分配内存时能够被成功分配到新生代的 Eden 空间中,避免在发生垃圾收集时频繁进行老年代的扩容。通过分配担保机制,可以减少垃圾收集的次数,提高垃圾收集的效率和性能。

大对象直接进入老年代

大对象就是需要大量连续内存空间的对象(比如:字符串、数组)。

大对象直接进入老年代的行为是由虚拟机动态决定的,它与具体使用的垃圾回收器和相关参数有关。大对象直接进入老年代是一种优化策略,旨在避免将大对象放入新生代,从而减少新生代的垃圾回收频率和成本。

  • G1垃圾回收器 会根据 -XX:G1HeapRegionSize 参数设置的堆区域大小和
    -XX:G1MixedGCLiveThresholdPercent参数设置的阈值,来决定哪些对象会直接进入老年代。

  • Parallel Scavenge垃圾回收器中,默认情况下,并没有一个固定的阈值
    (-XX:ThresholdTolerance是动态调整的)来决定何时直接在老年代分配大对象。而是由虚拟机根据当前的堆内存情况和历史数据动态决定

长期存活的对象进入老年代

虚拟机采用了分代收集的思想来管理内存,那么内存回收时就必须能识别哪些对象应放在新生代,哪些对象应放在老年代中。为了做到这一点,虚拟机给每个对象一个对象年龄(Age)计数器。

大部分情况,对象都会首先在 Eden 区域分配。如果对象在 Eden 出生并经过第一次 Minor GC 后仍然能够存活,并且能被 Survivor 容纳的话,将被移动到 Survivor 空间(s0 或者 s1)中,并将对象年龄设为 1(Eden 区->Survivor 区后对象的初始年龄变为 1)

对象在 Survivor 中每熬过一次 MinorGC,年龄就增加 1 岁,当它的年龄增加到一定程度(默认为 15 岁,可以通过参数 -XX:MaxTenuringThreshold 来设置),就会被晋升到老年代中。

Hotspot 遍历所有对象时,按照年龄从小到大对其所占用的大小进行累积,当累积的某个年龄大小超过了 survivor 区的一半(默认值是 50%,可以通过 -XX:TargetSurvivorRatio=percent 来设置)时,取这个年龄和 MaxTenuringThreshold更小的一个值,作为新的晋升年龄阈值。

主要进行 GC 的区域

![[Pasted image 20231011164054.png]]

来自知乎:RennaxelaFX 的回答

针对 HotSpot VM 的实现,它里面的 GC 其实准确分类只有两大种:

部分收集 (Partial GC):

Partial GC(Partial Garbage Collection) 指在JVM中进行局部垃圾收集的一种策略。它是垃圾收集器对整个堆内存进行部分清理的过程。

传统的垃圾收集器通常会触发整体垃圾收集Full GC),即对整个堆内存进行完整的清理。这种方式可能会造成较长的停顿时间,影响应用程序的响应性能。为了减少这种停顿时间,一些现代的垃圾收集器引入了 Partial GC 的概念。

Partial GC 的思想是将堆内存划分为多个区域,并在每个区域中进行独立的垃圾回收。通过局部的垃圾收集,可以只清理一部分的垃圾对象,而不是整个堆内存。这样可以减少垃圾收集的时间,并且只影响到部分区域,从而减少对应用程序的影响

Minor GC

新生代收集(Minor GC / Young GC):只对新生代进行垃圾收集;

在Java虚拟机中,内存分为不同的区域,其中新生代是对象被创建后分配的初始区域,大多数对象都在新生代中被分配。新生代又分为一个 Eden 区和两个 Survivor 区(通常是一个 From 区和一个 To 区)。

当新生代空间不足时,就会触发 Minor GC,主要目的是清理新生代中的垃圾对象,保留尚且存活的对象,并为新的对象分配空间

Minor GC的过程如下

  1. 初始阶段,首先将 Eden 区和 From 区中的存活对象复制到 To 区,并根据对象的年龄(根据对象经历的 Minor GC 次数)进行相应的处理。未达到晋升年龄阈值的对象会被复制到 To 区,年龄达到晋升年龄阈值的对象则复制到老年代。

  2. 如果对象经过多次 Minor GC 后仍然存活,会晋升到老年代。当对象达到老年代晋升条件时,即老年代空间不足时,也会触发 Full GC(Major GC)。

  3. 清理完成后,将 Eden 区和 From 区的对象内存清空,清理掉没有存活对象的空间,将 To 区和 From 区的角色互换,保持新生代的可用性。

Minor GC一般发生频率较高,且对整个堆内存的回收时间较短,因为新生代中的垃圾对象通常较少。因此,Minor GC对于程序的停顿时间影响较小

Minor GC 的效果和行为会受到具体的垃圾回收器和虚拟机配置参数的影响,不同的垃圾回收器对于新生代的管理方式和策略可能有所不同。

Major/Old GC

老年代收集 old GC 是指在 JVM 中针对老年代进行的垃圾收集操作。

Major GC 在有的语境中也用于指代整堆收集 Full GC

老年代是堆内存中存放长时间存活的对象的区域,通常包含已经经历过多次新生代垃圾收集的对象。

old GC 是为了回收不再使用的对象,释放内存空间以供新的对象使用。由于老年代中存储的对象通常比较大且存活时间较长,old GC 可能对系统性能产生较大影响。不同的垃圾收集器有不同的策略和算法来进行老年代的垃圾收集。

一些常见的老年代垃圾收集器包括:

  • CMS(Concurrent Mark Sweep) 收集器:CMS 收集器通过使用标记-清除算法来进行垃圾收集,并且在标记和清理阶段尽可能地与应用程序线程并发执行,以减少停顿时间。

  • G1(Garbage First) 收集器:G1 收集器是一种全局并发的垃圾收集器,它将整个堆内存划分为多个大小相等的区域,采用分代和并发的方式进行垃圾收集,以减小停顿时间。

  • Serial Old(串行老年代) 收集器:Serial Old 收集器是一种单线程的老年代收集器,它使用标记-整理算法进行垃圾收集。

具体选择哪种老年代垃圾收集器取决于应用程序的需求和系统环境。通常,性能较高的收集器可能会对系统产生更大的停顿时间,而并发的收集器可能会减小停顿时间但牺牲一些系统性能。

在选择老年代垃圾收集器时需要权衡性能需求、停顿时间和可用系统资源。

Mixed GC

Mixed GC(Mixed Garbage Collection) 是一种混合型的垃圾收集方式,在JVM中用于处理全部新生代和部分老年代的垃圾回收。它结合了部分清理和整体清理的特性,旨在提高垃圾收集器的性能和效率。

传统的垃圾收集器通常会针对不同代的垃圾进行独立的收集。例如,年轻代会使用年轻代的垃圾收集器,老年代会使用老年代的垃圾收集器,它们独立运作。

Mixed GC 则通过组合新生代和老年代的部分垃圾收集,以获得更好的性能。它的基本思想是在一次垃圾收集中同时处理新生代和老年代的垃圾,而不是分开进行。

Mixed GC的过程

  1. 进行新生代的垃圾回收,清理出生代(Eden空间和Survivor空间)中不再存活的对象。

  2. 将存活的对象晋升(Promotion)到老年代。

  3. 对老年代进行部分清理,回收一部分老年代中不再存活的对象。

这种混合的收集方式可以减少全局停顿时间,更充分地利用了整个堆内存的空间。

Mixed GC 通常是由支持分代收集的垃圾收集器 (如G1(Garbage First)收集器 实现的。它在收集时会根据各个分区中的垃圾数量、自适应的触发条件等因素来确定执行 Mixed GC 的时机和频率。通过动态地调整收集策略,Mixed GC 可以在保证垃圾回收效果的同时,减小垃圾收集的停顿时间。

Mixed GC 并不适用于所有的垃圾收集器,它主要应用于一些具有分代收集特性的垃圾收集器。在使用 Mixed GC 时,可以根据应用程序的需求和性能要求进行垃圾收集器的选择和配置。

整堆收集(Full GC)

Full GC(Full Garbage Collection),也称为Major GC,是指对整个Java堆(包括新生代和老年代)进行的完整垃圾回收操作。

Minor GC 只针对新生代进行部分回收不同,Full GC会同时清理新生代和老年代中的垃圾对象

选择何时触发 Major GC(Full GC)以及使用哪种垃圾收集器来执行 Major GC 是取决于特定 JVM 配置和垃圾收集器的决策。Full GC的触发条件通常包括以下几个方面

  1. 当新生代无法容纳要分配的对象,并且新生代中垃圾对象的占比较高时,可能会触发 Full GC 来尝试扩大新生代的空间。

  2. 对象在新生代经历了多次 Minor GC 后仍然存活,并且无法晋升到老年代时,会触发 Full GC 来释放空间。

  3. 当老年代空间不足以容纳大对象时,也会触发 Full GC 来进行整理和释放。

  4. 当调用 System.gc() 显式请求进行垃圾收集时,可能会触发 Major GC

Full GC的过程相对较为复杂和耗时,主要包括以下几个阶段

  1. 标记阶段(Marking Phase):从根对象开始,对整个堆内存中的所有对象进行可达性分析,标记出存活的对象。

  2. 清理阶段(Sweeping Phase):清理所有未标记的对象,即被认为是垃圾对象的对象。

  3. 压缩阶段(Compaction Phase):对堆内存进行压缩和整理,将存活对象向一端移动,以便留出连续的空间。

Full GC导致整个应用程序在清理和整理内存期间暂停,造成较长的停顿时间
应尽量避免频繁触发 Full GC。高效地调整堆内存大小、合理设置垃圾收集器以及优化应用程序的内存使用方式等手段可以降低 Full GC 的频率和影响。

需要注意的是,Full GC 的性能和行为会受到具体的垃圾回收器、堆内存配置参数和应用程序的内存使用情况等因素的影响,不同的情况下 Full GC 的触发和执行策略可能会有所不同。

空间分配担保

空间分配担保是为了确保在 Minor GC 之前老年代本身还有容纳新生代所有对象的剩余空间

JDK 6 Update 24 之前,在发生 Minor GC 之前,虚拟机必须先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果这个条件成立,那这一次 Minor GC 可以确保是安全的。如果不成立,则虚拟机会先查看 -XX:HandlePromotionFailure 参数的设置值是否允许担保失败(Handle Promotion Failure)

如果允许,那会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试进行一次 Minor GC,尽管这次 Minor GC 是有风险的;如果小于,或者 -XX: HandlePromotionFailure 设置不允许冒险,那这时就要改为进行一次 Full GC。

JDK 6 Update 24 之后的规则变为只要老年代的连续空间大于新生代对象总大小或者历次晋升的平均大小,就会进行 Minor GC,否则将进行 Full GC

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2140882.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

K-means 算法的介绍与应用

目录 引言 K-means 算法的基本原理 表格总结:K-means 算法的主要步骤 K-means 算法的 MATLAB 实现 优化方法与改进 K-means 算法的应用领域 表格总结:K-means 算法的主要应用领域 结论 引言 K-means 算法是一种经典的基于距离的聚类算法&#xff…

中秋献礼!2024年中科院一区极光优化算法+分解对比!VMD-PLO-Transformer-LSTM多变量时间序列光伏功率预测

中秋献礼!2024年中科院一区极光优化算法分解对比!VMD-PLO-Transformer-LSTM多变量时间序列光伏功率预测 目录 中秋献礼!2024年中科院一区极光优化算法分解对比!VMD-PLO-Transformer-LSTM多变量时间序列光伏功率预测效果一览基本介…

人工智能和大模型的简介

文章目录 前言一、大模型简介二、大模型主要功能1、自然语言理解和生成2、文本总结和翻译3、文本分类和信息检索4、多模态处理三、大模型的技术特性1、深度学习架构2、大规模预训练3、自适应能力前言 随着技术的进步,人工智能(Artificial Intelligence, AI)和机器学习(Mac…

TryHackMe 第1天 | Introduction to Cyber Security

偶然之间了解到了TryHackMe这个网站,尝试跟着其中的学习路径进行学习,发现还是挺适合入门网络安全这一领域的。但是这个网站包含了很多内容,如果不用一些东西记录下来,那么很容易忘记,所以打算在此记录一下学习过程。 …

Linux——应用层自定义协议与序列化

目录 一应用层 1再谈 "协议" 2序列化与反序列化 3理解read,write,recv,send 4Udp vs Tcp 二网络版本计算器 三手写序列和反序列化 四进程间关系与守护进程 1进程组 1.1什么是进程组 1.2组长进程 2会话 2.1什么是会话 2.2会话下的前后台进程 3作业控…

nginx实现权重机制(nginx基础配置二)

在上一篇文章中我们已经完成了对轮询机制的测试,详情请看轮询机制。 接下来我们进行权重机制的测试 一、conf配置 upstream backServer{ server 127.0.0.1:8080 weight2; server 127.0.0.1:8081 weight1; } server { listen 80; server_name upstream.boyatop.cn…

一个有趣的“苦无”测试探针笔的设计

设计思路来源 动漫火影中的苦无,在测试过程中多种测试点方便测试,不想每次去找合适的测试工具,例如点测试和连接线测试需要用到不同的接触工具。 PCB设计 这这些焊点都是短接的(除了中间的固定孔),直接使…

Leetcode 验证回文串

使用双指针技术,逐步比较字符串中的字符,并忽略非字母数字字符以及大小写,判断该字符串是否为回文。以下是详细解释: 1. 核心思想: 回文串是指正读和反读都相同的字符串。我们需要从字符串的两端开始比较字符&#x…

Python画笔案例-051 绘制赵爽弦图

1、绘制赵爽弦图 通过 python 的turtle 库绘制 赵爽弦图,如下图: 2、实现代码 绘制 赵爽弦图,以下为实现代码: """赵爽弦图.py本程序演录了如何自定义形状,如何把它添加到造型字典。赵爽弦图是用来证明…

JAVA算法数据结构第一节稀疏矩阵

一、稀疏矩阵介绍: 稀疏矩阵是一种特殊类型的矩阵,其中大部分元素都是零。在处理这类矩阵时,如果仍然使用标准的矩阵存储方式(即传统的二维数组),则会浪费大量的存储空间来保存零值。为了提高存储效率以及…

9.12 TFTP通信

客户端设计(仅供参考): 下载本质:读取服务器发送的数据包,写入到本地文件 上传本质:读取本地文件内容,发送给服务器。 1、建立菜单选项,上传和下载。 2、上传功能函数: …

实用类工具!分享6款AI论文一键生成器免费8000字

在当前的学术研究和写作领域,AI论文生成工具的出现极大地提高了写作效率和质量。这些工具不仅能够帮助研究人员快速生成论文草稿,还能进行内容优化、查重和排版等操作。千笔-AIPassPaper是一款备受推荐的AI论文一键生成器。 千笔-AIPassPaper是一个一站式…

centos更改静态ip

点击网络和internet设置 点击更改适配器 、点击属性

15.8 在k8s部署prometheus statefulset

本节重点介绍 : 检查,kube-system ns [rootprome-master01 prometheus]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE coredns-7d75679df-7f7tx 1/1 Running 0 88m coredns-7d75679df-qmzbg 1/1 Running 0 88m etcd-prome-master01 1/1 Runni…

实习期间git的分枝管理以及最常用的命令

各位找工作实习的友友在工作之前一定要把git的相关知识掌握呀,我实现期间被leader说过关于git规范的相关问题了 目前已更新系列: 当前::实习期间git的分枝管理以及最常用的命令 Redis高级-----持久化AOF、RDB原理 Redis高级---面试总结5种…

[网络]http请求中的URL,方法,header 和 http响应中的状态码

文章目录 一. http请求1. 认识URLurlencode 2. 认识方法应用场景构造http请求 2. 认识请求报头header 二. http响应1. 状态码 一. http请求 1. 认识URL 我们所说的"网址", 其实就是URL(Uniform Resource Locator 统⼀资源定位符) 1.协议方案名 常见的有http和http…

微信小程序----日期时间选择器(自定义时间精确到分秒)

目录 页面效果 代码实现 注意事项 页面效果 代码实现 js Component({/*** 组件的属性列表*/properties: {pickerShow: {type: Boolean,},config: Object,},/*** 组件的初始数据*/data: {pickerReady: false,// pickerShow:true// limitStartTime: new Date().getTime()-…

Acrobat 9 安装教程

软件介绍 Adobe Acrobat 是由Adobe公司开发的一款PDF(Portable Document Format,便携式文档格式)编辑软件。借助它,可以以PDF格式制作和保存文档,以便于浏览和打印,同时还可以使用一些高级工具来创建、编辑…

MySQL高可用配置及故障切换

目录 引言 一、MHA简介 1.1 什么是MHA(MasterHigh Availability) 1.2 MHA的组成 1.3 MHA的特点 1.4 MHA工作原理 二、搭建MySQL MHA 2.1 实验思路 2.2 实验环境 1、关闭防火墙和安全增强系统 2、修改三台服务器节点的主机名 2.3 实验搭建 1、…

庆祝中华人民共和国成立75周年答题活

为庆祝中华人民共和国成立75周年,弘扬爱国主义精神,激发广大党员干部和人民群众奋进新征程、建功新时代,奋力推进中国式现代化建设的爱国热情,“学习强国”学习平台采用“线上答题线下竞赛”的形式,举办“学习强国 强国…