03垃圾回收篇(D4_彻底理解GC)

目录

一、浅析大促备战过程中出现的 fullGc,我们能做什么?

1. 什么是 JVM 的 GC?

2. 写代码的时候能做什么?

3. 测试能做啥

4. 知识小结

二、MinorGC、MajorGC、FullGC垃圾回收介绍

1. MinorGC (新生代垃圾回收)

2. Major GC(老年代垃圾回收)

3. Full GC (新生代+老年代垃圾回收)


一、浅析大促备战过程中出现的 fullGc,我们能做什么?

1. 什么是 JVM 的 GC?

JVM(Java Virtual Machine)

JVM 是 Java 程序的虚拟机,是一种实现 Java 语言的解释器。

它提供了一种独立于操作系统的运行环境,使得 Java 程序在任何支持 JVM 的计算机上都可以运

行。

JVM 负责加载、验证、解释、执行和垃圾回收 Java 字节代码,并为 Java 程序提供内存管理、线

程管理和安全控制等服务。

JVM 中的 GC(Garbage Collection)是垃圾回收的缩写,是 JVM 的内存管理机制。

Young GC 和 Full GC 是两种不同的 GC 算法。

Young GC:针对新生代对象的回收算法,通常使用的是复制算法或者标记整理算法。因为新生代

中的对象生命周期短,所以 Young GC 速度要比 Full GC 快得多。

Full GC:针对整个堆内存的回收算法,用于回收那些在 Young GC 中没有回收的存活对象。Full

GC 速度比较慢,因为它需要扫描整个堆内存,因此对系统的性能影响较大。

所以在设计 Java 应用时,需要尽量减少 Full GC 的次数,以保证系统的性能。

常见的方法包括扩大新生代的内存空间,减少数组长度等。

以上基本是通用的对 Jvm 和 Gc 的解释。

但是可以明显看出缺少一些细节,对我们来说还是没什么用,测试同学该如何理解具体的场景呢??

我们首先来理解 young GC 的诞生过程:

首先, 理解复制算法和标记整理算法,它们是两种不同的 Young GC 回收算法。

复制算法:将新生代内存分成两个等大的部分,新创建的对象存储在一个部分,而另一个部分用于

存储存活的对象。当新生代内存不够用时,Young GC 会发生,将存活的对象复制到另一个内存区

域。复制算法不会导致内存碎片,但是会消耗一定的内存空间。

标记整理算法:每次 Young GC 时,会先标记所有存活的对象,然后再将所有不存活的对象整理

到一起。因此,内存碎片可能会导致空间浪费。标记整理算法适用于需要保持内存空间整洁的应

用,比如那些需要长时间运行的服务器应用。

这个看看就好,本质上 Young Gc 可以理解成 jvm 正常的扫垃圾过程

根据上述的解释,相信聪明的小伙伴可以清晰的看到,young Gc 有着更高的回收效率,对业务侧

的影响要小的多~因此,我们进一步来看看头痛的 full Gc,是怎么来的?

Full GC 是 Full Garbage Collection 的缩写,是指把整个堆内存扫描一遍,回收不再使用的对象并

且整理内存的过程。

由于堆内存的整体回收过程非常慢,因此,Full GC 可能导致应用程序的暂停。

如上所述,只有更合理的内存分配,避免不被使用的对象频繁出现,调整堆内存的扫描时间。

full GC,即全垃圾回收,是一种垃圾回收的过程 它会暂停所有的应用程序线程,对整个堆进行

回收。 (这个太可怕了。。)

  • 初始标记:首先,垃圾回收器标记出哪些对象是需要被回收的。
  • 并发标记:然后,垃圾回收器将标记任务分配给多个线程,并发地执行标记任务。
  • 重新标记:在并发标记的过程中,如果有新的对象被创建,需要对这些对象进行重新标记。
  • 整理:接下来,垃圾回收器将没有被标记的对象整理到内存的一端。
  • 回收:最后,垃圾回收器回收被标记的对象,释放内存。

来个图大家看的明白一些~ Full Gc 的生命流程~

本质上就是,垃圾太多,正常的活儿干不了了,内存空间不够了,得停下所有的事情,来一次大扫

2. 写代码的时候能做什么?

上述可得,fullGc 是很可怕的,由于堆内存的整体回收过程非常慢,因此,Full GC 可能导致应用

程序的暂停,直接就崩掉了。。。

要避免 Full GC 发生,本质上就需要对系统堆内存大小进行适当设置以及对代码进行优化,基本上

有以下这些 技巧:

  • 调整堆内存大小:确定合适的堆内存大小是避免 Full GC 发生的关键。
  • 对代码进行内存优化:使用不同的数据结构,避免内存泄漏,使用对象池等技巧。
  • 使用较大的新生代:新生代是存储短生命周期对象的内存区域,更大的新生代可以减少 Full GC 的频率。
  • 设置适当的垃圾回收算法:使用 G1 GC 算法等技术可以提高系统性能并减少 Full GC 的频率。

这些是避免 Full GC 发生的一些常见建议。请注意,每种情况都不同,所以要根据具体情况选择适

当的方法。这些方法,看起来还是很抽象...我们来说点具体例子

首先,堆内存大小和垃圾回收算法,不是咱能操作和关心的,业务侧也一般不怎么会调,交给运维

同学了。

浅提一下,调整内存大小:通过调整 JVM 参数,如 -Xms、-Xmx 来适当增大内存。

具体我们能做到的,最主要的就是减少数据对象的生命周期:

通过使用弱引用、软引用、虚引用等引用类型,可以在不需要数据对象时直接回收,从而避免 Full

GC 。

减少数据对象的生命周期是指在程序中使用对象时,尽可能地缩短对象的存活时间。

这样可以减少垃圾对象数量,降低 Full GC 的频率。

这是我们重点需要关注的!!

以下是一些具体的例子:

1. 避免使用不必要的临时对象:

如果程序中有大量临时对象,它们可能很快就会被垃圾回收器清理掉。因此,应该避免创建不必要

的临时对象,以减少对象的生命周期。

eg:

double average(double[] values) {
  
  

在这个例子中,数组 values 是临时对象,在函数结束时会被销毁。这样,不必考虑如何删除集

合,以避免内存泄漏的风险。

还有,

String concatenate(List<String> strings) {
  
  

在这个例子中,每次循环都会创建一个临时的字符串对象,并将其附加到 result 中。随着循环的进

行,这些临时对象可能会堆积,导致频繁的 GC 操作。为了避免这个问题,可以使用 Java 中的

StringBuilder 来构建字符串

String concatenate(List<String> strings) {
  
  

这样的话,不再需要创建临时字符串对象,从而减少 GC 的次数。

2. 尽早释放对象:当对象不再需要时,应该尽早将其释放,以便及时回收它。

例如,在程序完成处理后立即释放对象,而不是等到下一次需要使用它之前。

比如我们日常最常用的 for 循环就很棒,

for (int i = 0; i < data.length; i++) {
  
  

在这个例子中,循环变量 i 只在循环中使用,并在循环结束后释放。这样做可以减少不必要的内存

使用,从而减少全垃圾回收的次数。

另一个具体的例子是使用 try-with-resources 语句,这可以确保流等资源在不再使用后自动关闭,

例如:try (FileInputStream in = new FileInputStream("file.txt")) {

在这个例子中,文件输入流在不再使用后会被自动关闭,就不用手动关,这样也会更合理~

3. 重复使用对象:如果可以,可以尝试重复使用同一个对象,而不是频繁地创建和销毁新的对象。

这个比较好理解,比如同样的事务流程,没必要搞两个变量 ~ 最少的变量干最多的活儿是最理想

的~

4. 使用对象池:

可以使用对象池,重复使用固定数量的对象,而不是不断创建新的对象。这样可以减少对象的生命

周期,并降低Full GC 的频率。

使用对象池是一种常用的避免 Full GC 的方式。它的核心思想是重复利用已经创建好的对象,而不

是每次都创建新的对象。

以下是一个简单的对象池的代码例子:

import java.util.ArrayList;

在代码中,我们创建了一个大小为 100 的对象池,并在静态代码块中初始化了 100 个对象。当我

们需要使用对象时,可以调用 getObject 方法,如果对象池中有剩余的对象,就从对象池中取出一

个对象;如果没有剩余对象,就新建一个对象。当不需要这个对象了,就可以调用 returnObject 方

法,将对象放回对象池中。这样,我们可以重复利用已经创建好的对象,减少了对象的创建和销毁

的频率,从而减少了 Full GC 的几率。

5. 使用弱引用:

在程序中,如果有大量对象不会再使用,可以使用弱引用来引用它们。 这个最多应用在类型缓存

这样的场景,它们不是必须的对象,因此有些时候可以直接干掉这是一个弱引用的例子,这玩意儿

还是比较抽象的。。。

import java.lang.ref.WeakReference;

举个更具体点的:

import java.lang.ref.WeakReference;

这个例子中,我们将一个 MyObject 对象封装在弱引用中,并保存在 HashMap 缓存中,当我们显

式调用

System.gc()方法时,JVM 会尝试回收这些不再使用的对象,如果内存不足,则会回收 MyObject

对象,那么cache.get("example").get()返回的将是 null。

3. 测试能做啥

回顾全文,其实我们能做的真不多,只能在业务代码测试的过程中,

关注对象的使用频次,拒绝无效的引用或 new 一大堆没必要的对象。

具体手段:

定期监测 GC 日志:通过我们的 jvm 关注,大项目上线后,或代码改动特别大的项目上线后,

做一下读写压测的操作

数据结构优化: 根据上述的手段,测试开发工程师可以通过上述手段,来优化数据结构来减小数

据对象的生命周期,从而避免 Full GC。

在测试过程中,关注一下数据结构的合理性~

关注单元测试:通过运行研发的单元测试,或自己手动写一个,模拟实际的内存使用情况,来评估

内存的使用情况(基本上,目前的业务代码能跑起来,大概率是没问题的,,)

4. 知识小结

日常的业务代码测试,对内存的敏感度要高一些,没 bug 不一定不会出问题,现在我们的系统是

成熟的可靠的,但是面对大促的压力,如果能提前解决隐患,干掉有风险的内存使用,也是节省我

们压测时的工作量嘛

二、MinorGC、MajorGC、FullGC垃圾回收介绍

今天给大家继续分享MinorGC、MajorGC、FullGC相关知识,如有不对的地方欢迎指正!

1. MinorGC (新生代垃圾回收)

JDK1.8 堆内部结构

从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC,也叫Young GC。因为

Java对象大多具备朝生夕死的特征,所以MinorGC非常频繁,一般回收速度也比较快。一般采用复

制算法。

说明:Minor GC可能会引发STW,暂停其他用户的线程,需要等JVM垃圾回收结束后,用户线程

才恢复运行。

Minor GC 触发条件

  • Eden伊甸园区满了
  • 新new的对象需要分配到新生代的Eden伊甸园区,当Eden区的空间不够的时候需要进行MinorGC策略回收,

2. Major GC(老年代垃圾回收)

Major GC指发生在老年代的GC。

Major GC触发条件

老年代空间不足时,会先尝试触发Minor GC。Minor GC之后空间还不足,则会触发Major GC。

说明:发生在老年代的GC ,基本上进行一次Major GC 就会伴随进行一次 Minor GC。

Major GC 的速度一般会比 Minor GC 慢 10 倍,并且STW的时间更长。

3. Full GC (新生代+老年代垃圾回收)

Full GC可以理解为Major GC+Minor GC组合后进行的一整个过程,是清理JVM整个堆空间

(年轻代和老年代空间)。

Full GC触发条件

  • 调用System.gc()方法时,可通过-XX:+ DisableExplicitGC 参数来禁止调用System.gc()
  • 当方法区空间不足时
  • Minor GC后存活的对象大小超过了老年代剩余空间
  • Minor GC时中Survivor幸存区空间不足时,判断是否允许担保失败,不允许则触发Full GC。允许,并且每次晋升到老年代的对象平均大小>老年代最大可用连续内存空间,也会触发Full GC
  • CMS GC异常,CMS运行期间预留的内存无法满足程序需要,就会出现一次“Concurrent ModeFailure”失败,会触发Full GC

STW(Stop The World):垃圾回收发生过程中,会产生应用程序的停顿现象。停顿产生的时候

整个应用程序线程都会被暂停,有点应用程序像卡死的情况。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件测试 —— jmeter(2)

软件测试 —— jmeter&#xff08;2&#xff09; HTTP默认请求头&#xff08;元件&#xff09;元件作用域和取样器作用域HTTP Cookie管理器同步定时器jmeter插件梯度压测线程组&#xff08;Stepping Thread Group&#xff09;参数解析总结 Response Times over TimeActive Thre…

分子动力学模拟里的术语:leap-frog蛙跳算法和‌Velocity-Verlet算法

分子动力学模拟&#xff08;Molecular Dynamics Simulation&#xff0c;简称MD&#xff09;是一种基于经典力学原理的计算物理方法&#xff0c;用于模拟原子和分子在给定时间内的运动和相互作用‌。以下是关于分子动力学模拟的一些核心术语和概念&#xff1a; ‌定义系统‌&am…

在 Windows 11 中为 SMB 3.x 文件共享协议提供 RDMA 支持

注&#xff1a;机翻&#xff0c;未校。 Enable SMB Direct in Windows 11 在 Windows 11 中启用 SMB Direct Provides RDMA support for the SMB 3.x file sharing protocol 为 SMB 3.x 文件共享协议提供 RDMA 支持 Vigneshwaran Vijayakumar November 3, 2024 Last Updat…

zabbix6.0安装及常用监控配置

文章目录 部署zabbix-serverzabbix监控节点部署解决zabbix中文乱码创建主机组创建模版配置主机与模版关联 监控boot分区监控网卡流量出网卡流量监控进入和出的总流量监控内存监控服务器端口用户自定应监控key值 (监控mysql查询数量)zabbix触发器监控cpu监控入网卡流量 邮件告警…

如何将使用unsloth微调的模型部署到ollama?

目录 一、将模型保存为gguf格式 二、下载llama.cpp 三、生成 llama-quantize 可执行文件 四、使用llama-quantize 五、训练模型 六、将模型部署到ollama 一、将模型保存为gguf格式 在你的训练代码 trainer.train() 之后添加&#xff1a; model.save_pretrained_gguf(&q…

【Hadoop面试题2025】

文章目录 简单题故障及相应的处理方法中等难度高难度小文件小文件的产生小文件问题的影响小文件治理方案推荐方案 冷文件冷文件的产生冷文件问题的影响冷文件治理方案推荐方案 简单题 一、基础概念类 什么是Hadoop&#xff1f; 答案&#xff1a;Hadoop是一个开源的分布式计算框…

2025.1.21——六、BUU XSS COURSE 1 XSS漏洞|XSS平台搭建

题目来源&#xff1a;buuctf BUU XSS COURSE 1 目录 一、打开靶机&#xff0c;整理信息 二、解题思路 step 1&#xff1a;输入框尝试一下 step 2&#xff1a;开始xss注入 step 3&#xff1a;搭建平台 step 4&#xff1a;利用管理员cookie访问地址 三、小结 二编&#…

[论文阅读] (36)CS22 MPSAutodetect:基于自编码器的恶意Powershell脚本检测模型

《娜璋带你读论文》系列主要是督促自己阅读优秀论文及听取学术讲座&#xff0c;并分享给大家&#xff0c;希望您喜欢。由于作者的英文水平和学术能力不高&#xff0c;需要不断提升&#xff0c;所以还请大家批评指正&#xff0c;非常欢迎大家给我留言评论&#xff0c;学术路上期…

IPhone16 Plus 设备详情

目录 产品宣传图内部图——前内部图——后设备详细信息 产品宣传图 内部图——前 内部图——后 设备详细信息 信息收集于HubWeb.cn

PyTorch入门 - 为什么选择PyTorch?

PyTorch入门 - 为什么选择PyTorch? Entry to PyTorch - Why PyTorch? by JacksonML $ pip install pytorch安装完毕后&#xff0c;可以使用以下命令&#xff0c;导入第三方库。 $ import pytorch

Jmeter 动态参数压力测试时间段预定接口

&#x1f3af; 本文档详细介绍了如何使用Apache JMeter进行压力测试&#xff0c;以评估预定接口在高并发场景下的性能表现。通过创建线程组模拟不同数量的用户并发请求&#xff0c;利用CSV文件动态配置时间段ID和用户token&#xff0c;确保了测试数据的真实性和有效性。文档中还…

字节跳动自研HTTP开源框架Hertz简介附使用示例

字节跳动自研 HTTP 框架 Hertz Hertz 是字节跳动自研的高性能 HTTP 框架&#xff0c;专为高并发、低延迟的场景设计。它基于 Go 语言开发&#xff0c;结合了字节跳动在微服务架构中的实践经验&#xff0c;旨在提供更高效的 HTTP 服务开发体验。 1. 背景介绍 随着字节跳动业务…

Spring Boot 自定义属性

Spring Boot 自定义属性 在 Spring Boot 应用程序中&#xff0c;application.yml 是一个常用的配置文件格式。它允许我们以层次化的方式组织配置信息&#xff0c;并且比传统的 .properties 文件更加直观。 本文将介绍如何在 Spring Boot 中读取和使用 application.yml 中的配…

HarmonyOS Next构建工具 lycium 原理介绍

HarmonyOS Next构建工具 lycium 原理介绍 背景介绍 HarmonyOS Next中很多系统API是以C接口提供&#xff0c;如果要使用C接口&#xff0c;必须要使用NAPI在ArkTS与C间交互&#xff0c;这种场景在使用DevEco-Studio中集成的交叉编译工具&#xff0c;以及cmake构建工具就完全够用…

数据结构(Java)——二叉树

1.概念 二叉树是一种树形数据结构&#xff0c;其中每个节点最多有两个子节点&#xff0c;通常被称为左子节点和右子节点。二叉树可以是空的&#xff08;即没有节点&#xff09;&#xff0c;或者由一个根节点以及零个或多个左子树和右子树组成&#xff0c;其中左子树和右子树也分…

ansible自动化运维实战--script、unarchive和shell模块(6)

文章目录 一、script模块1.1、功能1.2、常用参数1.3、举例 二、unarchive模块2.1、功能2.2、常用参数2.3、举例 三、shell模块3.1、功能3.2、常用参数3.3、举例 一、script模块 1.1、功能 Ansible 的 script 模块允许你在远程主机上运行本地的脚本文件&#xff0c;其提供了一…

【期末速成】Oracle数据库

选择题 从中选 10 道。 Oracle的管理与开发工具不包括&#xff08; D &#xff09;。 A. OEM B. SQL*PLUS C. ONCA D. PHP PHP 是一种编程语言&#xff0c;不是 Oracle 的工具。 下面文件属于物理文件的是&#xff08; C &#xff09;。 A. 概要文件 B. 闪回文件 C. 数据文件 D…

auto的用法

文章目录 一、auto 一、auto 在这里插入代码片在这里插入代码片感谢大家能看到这里&#xff0c;多多支持&#xff01;

UE求职Demo开发日志#7 强化属性完善

1 实现思路设计 定义一个结构体记录技能树一个单元的信息&#xff0c;命名为FStrengthenCellInfo&#xff0c;一个TArray记录技能树整体信息&#xff0c;需要以下信息&#xff1a; 1.TArray前置技能index 2.FString 描述文本 3.TArray<FMyItemInfo>激活需要的物品ID和…

java常量池

目录 1 Class常量池 2 运行时常量池 3 字符串常量池 3.1 为什么要设计字符串常量池 3.2 字符串对象三种创建姿势 3.3 字符串的操作 3.4 字符串的不可变性 4 包装类型常量池 1 Class常量池 class 文件的资源仓库javap命令可以查看class常量池 主要包含字面量和符号引用字面量 由…