谈谈Minor GC、Major GC和Full GC

目录

一、背景

二、三者之间的区分

1、Minor GC

2、Major GC

(1)老年代空间不足:

(2)晋升(Promotion)失败:

(3)空间分配担保失败:

(4)显式调用:

3、Full GC

三、总结

四、JVM调优参数分享

一、背景

在我们工作中,虽然我们更多的是写代码的,但是Java的内存机制我们其实是无时无刻都在打交道,项目运行要多少内存评估,上线后是否能抗住流量,Java内存中新生代、老年代的比例设置比例是多少等等。这次主要是讲讲我们常接触的GC中的Minor GC、Major GC、FullGC到底有什么区别以及在工作中应该如何注意减少GC的频率

二、三者之间的区分

1、Minor GC

Minor GC,它的全称是(Young Generation Garbage Collection)是指对年轻代(Young Generation)进行的垃圾回收操作。所以说白了其实就是对年轻代的区域进行回收

在Java虚拟机中,堆内存被划分为不同的区域,其中年轻代是对象分配的主要区域。Minor GC主要负责回收年轻代的垃圾对象。

年轻代通常分为三个区域:Eden区和两个Survivor区(一般称为From区和To区)。当对象被创建时,它们会被分配到Eden区。在年轻代的垃圾回收过程中,首先会对Eden区进行垃圾回收,将存活的对象复制到一个空闲的Survivor区中(通常是To区),同时清空Eden区。如果Survivor区无法容纳所有存活的对象,一部分对象会被直接晋升到老年代(Tenured Generation)。

所以我们的Minor GC 在我们的程序运行的过程中其实是很频繁的,因为我们的代码如一些接口、消费者类,定时任务等都会很频繁的创建对象和销毁对象,这些对象大部分在新生代里面,有朝生夕死的特点在多次Minor GC后,存活时间较长的对象会逐渐被移到Survivor区,并经过多次复制和清理的过程。当对象经历了一定次数的复制后,会被认为是长时间存活的对象,最终会被晋升到老年代。

总结:Minor GC通常是并行或并发执行的,意味着在垃圾回收期间,应用程序的执行可能会暂停或降低速度。为了减少这种停顿时间,一些垃圾回收器,如并行垃圾回收器(Parallel GC)和G1垃圾回收器(Garbage-First GC),采用了并发标记和清理的方式。

总之,Minor GC是一种针对年轻代进行的垃圾回收操作,主要目的是回收年轻代的垃圾对象,以保证堆内存的有效利用和应用程序的性能。所以总而来说Minor GC在我们的应用程序的运行过程中,确实是比较频繁的操作,大家如果看到MinorGC 很频繁,也不必过分惊慌。

2、Major GC

什么是Major GC?
Major GC的全称是(Major Garbage Collection)是指对Java虚拟机中的老年代(Tenured Generation)进行的垃圾回收操作。与Minor GC主要关注年轻代的回收不同,Major GC专注于回收老年代中的垃圾对象。

所以其实你可以理解为和Minor GC的区别是前者是专门用于年轻代对象回收的机制,后者是用于老年代的对象回收。

在Java堆内存中,老年代用于存放生命周期较长的对象或者经过多次Minor GC后仍然存活的对象。随着时间的推移,老年代中的垃圾对象会逐渐增加,因此需要进行周期性的垃圾回收来释放这些占用的内存空间。

Major GC的触发条件通常是由JVM自动管理的,具体条件可能因不同的JVM实现和垃圾回收器而有所不同。它可能在以下情况下触发:

1. 老年代空间不足:当老年代无法容纳新对象或晋升对象时,会触发Major GC来回收老年代的垃圾对象。

2、永久代垃圾回收:如果使用的是传统的垃圾回收器(如Parallel GC、CMS等),那么Major GC也会包含对永久代(Permanent Generation)的垃圾回收操作,用于清理无效的类定义、常量等。

3、JVM显式调用:通过System.gc()或Runtime.getRuntime().gc()等方式显式调用垃圾回收,可能会触发Major GC。

Major GC的执行时间一般比Minor GC更长,因为它需要处理较多的对象和进行更复杂的内存整理操作。在Major GC期间,应用程序的执行将会暂停,直到垃圾回收操作完成。了解Major GC对于应用程序的性能分析和调优非常重要,适当配置堆大小、调整垃圾回收器参数等可以减少Major GC的频率和停顿时间,以提高应用程序的吞吐量和响应性能。

2、再完整总结下,什么情况下会触发Major GC?
Major GC(Major Garbage Collection)在Java虚拟机中会在以下情况下被触发:

(1)老年代空间不足:

当老年代(Tenured Generation)无法容纳新对象或晋升对象时,会触发Major GC来回收老年代的垃圾对象。这种情况通常发生在频繁创建大对象或者持久对象导致老年代空间快要满了的情况下。(这个应该是比较常见的一种现象,随着我们的程序运行的越来越久,生成的老年代的对象越来越多,可能就会触发Major GC来进行空间回收

(2)晋升(Promotion)失败:

在年轻代(Young Generation)中的对象经过多次Minor GC后仍然存活并且达到了晋升的条件,但是老年代空间不足以容纳它们时,也会触发MajorGC。这种情况可能是因为年轻代中的对象生命周期较长,导致垃圾对象聚集在老年代中。(如果发生这种情况,我们应该注意,说明是不是我们程序是否有一些高频的创建对象的行为,并且是较大的对象,导致大量大对象往老年代迁移,具体的体现行为例如有:接口流量激增,定时任务查询的数据库数据过多,大数据量导出等,观察项目的运行情况有利于我们找到频繁Marjor GC的原因)

(3)空间分配担保失败:

在进行Minor GC时,如果老年代的连续内存空间不足以容纳晋升对象,JVM会尝试进行一次Minor GC并且通过移动对象来释放更多的连续空间。如果这个过程之后仍然无法满足空间需求,那么会触发Major GC。

(4)显式调用:

通过System.gc()或Runtime.getRuntime().gc()等方式显式调用垃圾回收,也有可能触发Major GC。不过请注意,Java虚拟机对于显式调用垃圾回收的处理是可选的,因此并不保证一定会触发Major GC。

总结:具体的Major GC触发条件可能因不同的JVM实现和垃圾回收器而有所不同。此外,Major GC的具体行为和执行策略也会受到所使用的垃圾回收器的影响。因此,在实际应用中,可以通过调整堆大小、调整垃圾回收器参数等方式来影响Major GC的触发频率和行为,以优化应用程序的性能。

3、Full GC

Full GC(Full Garbage Collection)是Java虚拟机(JVM)中的一种垃圾回收操作。它是指对整个堆内存进行回收,包括新生代和老年代。如果一旦遇到Full GC那一定得重视起来,因为可能程序Full GC的频率很高就会容易导致程序不稳定甚至崩溃。

在Java中,垃圾回收器通常会将堆内存划分为不同的区域,如新生代和老年代。当新生代空间不足时,会触发Minor GC,只清理新生代内存。而当老年代空间不足或者为了整理碎片化的内存,就有可能会触发Full GC,对整个堆内存进行回收。同时永久代(元空间)不足也有可能触发Full GC。本人就有一次在公司遇到频繁Full GC,就是因为元空间不足导致,调大了元空间的初始化内存即可进行优化。

Full GC 可能会导致较长的停顿时间,因为它需要扫描整个堆内存,标记可回收对象,并进行内存整理。这意味着在 Full GC 过程中,应用程序的执行会被暂停。

Full GC 的频率会受多种因素影响,如堆内存的大小、JVM配置参数、对象分配速度等。如果 Full GC 发生过于频繁或耗时过长,可能会导致应用程序的性能下降。所以一旦遇到频繁的Full GC一定要重视起来

为了减少 Full GC 的频率和时间,我们可以采取以下策略:

  • 调整堆内存大小:适当设置堆内存大小,避免过小的情况。可以在一开始的时候就设置好初始化内存和最大内存一致,防止内存抖动导致应用程序不稳定。
    • 设置堆内存
      • 初始堆大小 (-Xms): 指定JVM启动时初始分配的堆内存大小。

      • 最大堆大小 (-Xmx): 指定JVM可以使用的最大堆内存大小。

  • 优化对象分配:在代码里面能复用的对象尽量复用,不过频繁的创建对象,这样会导致程序不稳定以及触发Full GC。
  • 尽可能使用较新的垃圾回收器,有条件用G1的就用G1,或者选择CMS,过老的垃圾回收器性能较差。
  • 进行代码优化:减少内存泄漏和不必要的对象引用,使垃圾回收更高效。

三、总结

Minor GC(Young Generation Garbage Collection)和Major GC(Major Garbage Collection)、Full GC(Full Garbage Collection)都是Java虚拟机中的垃圾回收操作,但它们的执行对象和目的略有不同。

Minor GC主要针对年轻代(Young Generation)进行垃圾回收,即对Eden区和Survivor区进行清理。它的目的是回收年轻代的垃圾对象,以保证堆内存的有效利用和应用程序的性能。Minor GC通常频繁发生,但每次垃圾回收的停顿时间较短。

而Full GC是对整个堆内存进行垃圾回收,包括年轻代和老年代(Tenured Generation)。Full GC的触发条件相对复杂,通常情况下会在以下几种情况下触发:当年轻代无法容纳对象、永久代(Permanent Generation)满了。Full GC的目的是回收整个堆内存中的垃圾对象,并进行一些更为耗时的操作,如处理永久代中的无效类、对堆内存进行碎片整理等。因此,Full GC通常会导致较长的停顿时间,对应用程序的性能会产生比较大的影响。

四、JVM调优参数分享

这里分享几个JVM调优的参数,都是基于实际的场景并且经过验证、现在生产环境就是这样配置

-XX:+UseContainerSupport 基于容器化启动,参数允许JVM自动根据容器的资源限制来调整其内部资源分配,这样可以更好地利用容器的资源,同时避免因资源分配不当导致的性能问题。 容器化启动必备
-XX:MaxRAMPercentage=40.0 容器化JVM内存分配比例,假设容器是4g,则将JVM内存设置为1.6g
-XX:InitialRAMPercentage=40.0 同上
-XX:MinRAMPercentage=40.0 同上
-XX:MetaspaceSize=512m 元空间内存大小
-XX:MaxMetaspaceSize=512m 最大之所以设置和初始化一样,就是防止元空间自增导致的系统的抖动
-XX:+UseG1GC 使用G1垃圾回收器
-XX:+PrintGCDetails 打印GC日志,也是相当实用的一个配置
-XX:+PrintHeapAtGC 在GC的时候打印堆信息,用于在GC的时候辅助分析问题,也是比较实用
-XX:+PrintGCDateStamps 输出gc时间
-Xloggc:/app/logs/myapplication-%t.gclog gc日志位置
-XX:+HeapDumpOnOutOfMemoryError 用于当虚拟机出现内存溢出异常时,Dump出当前的内存堆转存快照以便事后分析
-XX:+ExitOnOutOfMemoryError JVM将在抛出OutOfMemoryError时立即退出,用于内存溢出时退出应用,以便容器重启应用,相当实用的一个配置
-XX:HeapDumpPath=/app/dump/myapplications.hprof dump文件地址

其实可以看到这里并没有太多的参数调优,实际情况下,JVM已经把垃圾回收器做得足够好了,很多时候它的默认参数已经是比较好的调优了,这里只是设置了一些堆的大小,包括记录一些内存溢出或者GC时的一些信息,方便分析问题。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1.4-蜜罐\堡垒机\API接口

1.4-蜜罐\堡垒机\API接口 蜜罐&#xff1a;用来钓鱼或诱惑测试人员的防护系统 bash <(curl -sS -L https://hfish.net/webinstall.sh) # 安装HFISH蜜罐堡垒机&#xff1a; 运维用的&#xff0c;统一管理运维平台;拿下堡垒机就很有可能等于拿下了多个平台 jumpServer一键安…

右值和右值引用【C++】

文章目录 左值引用和右值引用简单介绍左值&#xff1a;右值&#xff1a;左值引用&#xff0c;引用右值右值引用&#xff0c;引用左值为什么强制类型转换之后&#xff0c;右值引用就可以引用左值了呢&#xff1f; 右值引用的作用举个例子理解移动构造和移动赋值的作用&#xff1…

罗杰斯特回归

定义 逻辑回归其实就是原来的线性回归加了激活函数&#xff0c;这个函数其实就是sigmoid函数&#xff0c;把一个回归的连续数值压缩到了0到1的空间&#xff0c;其实只要有函数能够满足把数值压缩到0,1之间就可以&#xff08;因为0到1之间的数值就是概率值&#xff09; 对于分类…

Elasticsearch 高级

Elasticsearch 高级 建议阅读顺序&#xff1a; Elasticsearch 入门Elasticsearch 搜索Elasticsearch 搜索高级Elasticsearch高级&#xff08;本文&#xff09; 1. nested 类型 1.1 介绍 Elasticsearch 中的 nested 类型允许你在文档内存储复杂的数据结构&#xff0c;比如一个…

基于SpringBoot实现的高校实验室管理平台功能四

一、前言介绍&#xff1a; 1.1 项目摘要 随着信息技术的飞速发展&#xff0c;高校实验室的管理逐渐趋向于信息化、智能化。传统的实验室管理方式存在效率低下、资源浪费等问题&#xff0c;因此&#xff0c;利用现代技术手段对实验室进行高效管理显得尤为重要。 高校实验室作为…

leetcode_704. 二分查找_java

704. 二分查找https://leetcode.cn/problems/binary-search/ 1.题目 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。 示…

python基础学习三(元组及字符串的使用)

文章目录 元组什么是元组元组的创建方式为什么要将元组设计成不可变序列元组的遍历集合集合的相关操作集合操作集合的数学操作集合生成式列表&#xff0c;字典&#xff0c;元组&#xff0c;集合总结 字符串字符串的驻留机制判断字符串的操作方法字符串的比较操作字符串的切片操…

游戏被外挂攻破?金融数据遭篡改?AI反作弊系统实战方案(代码+详细步骤)

一、背景与需求分析 随着游戏行业与金融领域的数字化进程加速,作弊行为(如游戏外挂、金融数据篡改)日益复杂化。传统基于规则的防御手段已难以应对新型攻击,而AI技术通过动态行为分析、异常检测等能力,为安全领域提供了革命性解决方案。本文以游戏反作弊系统和金融数据安…

深入理解 TypeScript 中的类型断言(Type Assertion)

类型断言是 TypeScript 中一个强大而独特的特性&#xff0c;它允许开发者告诉编译器&#xff1a;"我知道这个值的类型是什么&#xff0c;请相信我"。本文将全面探讨类型断言的概念、语法、使用场景、最佳实践以及潜在陷阱&#xff0c;帮助你在 TypeScript 开发中更有…

matplotlib标题比x,y轴字体大,明明标题字体更大?

原始代码&#xff1a; plt.xlabel(训练轮次&#xff08;Epochs&#xff09;, fontsize14, fontweightbold, fontpropertieschinese_font) # 设置中文字体、加大、加粗 plt.ylabel(R值, fontsize14, fontweightbold, fontpropertieschinese_font) # 设置中文字体、加大、加粗…

MySQL DQL,数据查询语言的用法

语法&#xff1a;select 字段名 from 表名 [where <条件>]选择符合条件的记录 group by 字段名表 :分组 having <条件> :选择符合条件的组 order by 字段名表 …

Python练习之抽奖界面

前言 一、代码整体架构分析 1、数据层 (Model) 2、控制层 (Controller) 3、视图层 (View) 二、核心功能实现详解 1、 文件导入功能 1.1、实现逻辑 1.2、代码涉及知识点讲解 1.2.1、wildcard 1.2.2、wx.FileDialog 1.2.3、dlg.ShowModal() 2、抽奖动画控制 1.1、…

Vue3 项目通过 docxtemplater 插件动态渲染 .docx 文档(带图片)预览,并导出

Vue3 项目通过 docxtemplater 插件动态渲染 .docx 文档&#xff08;带图片&#xff09;预览&#xff0c;并导出 预览安装插件示例代码项目目录结构截图实际效果截图 动态渲染 .docx 文档&#xff08;带图片&#xff09;&#xff0c;预览、导出安装插件docx 模板文件内容完整代码…

springmvc redirect 使用https后跳转到了http://域名:443问题处理

最近在处理一个很久之前的项目的时候&#xff0c;由于需要将http升级到https&#xff0c;导致springmvc项目中配置的redirect报错 线上的返回结果是http://abc.test.com:443/jrbac/mobile/wechat.html 通过nginx配置了一下解决了&#xff0c;记录一下 location /jrbac {proxy…

用空闲时间做了一个小程序-二维码生成器

一直在摸鱼中赚钱的大家好呀~ 先向各位鱼友们汇报一下情况&#xff0c;目前小程序已经有900的鱼友注册使用过。虽然每天都有新的鱼友注册&#xff0c;但是鱼友增长的还很缓慢。自从国庆前的文字转语音的工具上线到现在已经将近有1个月没有更新小程序了。但是今天终终终终终于又…

【JavaEE】springMVC返回Http响应

目录 一、返回页面二、Controller和ResponseBody与RestController区别三、返回HTML代码⽚段四、返回JSON五、HttpServletResponse设置状态码六、设置Header6.1 HttpServletResponse设置6.2 RequestMapping设置 一、返回页面 步骤如下&#xff1a; 我们先要在static目录下创建…

【新手初学】SQL注入getshell

一、引入 木马介绍&#xff1a; 木马其实就是一段程序&#xff0c;这个程序运行到目标主机上时&#xff0c;主要可以对目标进行远程控制、盗取信息等功能&#xff0c;一般不会破坏目标主机&#xff0c;当然&#xff0c;这也看黑客是否想要搞破坏。 木马类型&#xff1a; 按照功…

验证Linux多进程时间片切换的程序

​​ 一、软件需求 在同时运行多个CPU密集型进程时&#xff0c;需采集以下统计信息&#xff1a; 当前运行在逻辑CPU上的进程ID每个进程的运行进度百分比 实验程序设计要求&#xff1a; 1. 命令行参数 参数说明示例值n并发进程数量3total总运行时长&#xff08;毫秒&…

Spring笔记03-依赖注入

简述: Spring 依赖注入&#xff08;Dependency Injection&#xff0c;DI&#xff09;是 Spring 框架的核心功能之一&#xff0c;它通过将对象的依赖关系交由 Spring 容器来管理&#xff0c;实现了对象之间的解耦&#xff0c;提高了代码的可维护性和可测试性。 构造器注入示例:…

减少采样空间方法 变成后验概率

又 因为后验概率很难计算 --所以通过引入变分分布来近似 后验概率分布 同时 引入 kl散度来度量 近似的效果好不好 什么是kl散度 kl散度带变分&#xff1a; 第一个问题 &#xff1a;积分变期望 问题二&#xff1a;贝叶斯公式 第三个问题&#xff1a;为啥可以独立出来 因为相比…