jvm之GC

news2024/12/26 10:55:30

写在前面

本文一起看下GC相关的内容。

1:GC基础内容

1.1:为什么要有GC

内存资源的稀缺性,以及内存管理的复杂性,决定了需要有垃圾回收器这样的角色来帮助我们管理内存资源,避免手动管理带来的内存不能得到正常释放,内存资源异常耗尽等问题。

1.2:GC如何确定垃圾对象

GC想要进行垃圾回收,就需要首先确定哪些对象是垃圾对象,当前有两种方式:

1:引用计数
2:引用追踪

1.2.1:引用计数

这种方式是统计计算对象被应用的次数,来确定对象是否是垃圾对象,如下图:

在这里插入图片描述

但是引用计数的方式存在循环引用的问题,如下图:

在这里插入图片描述

此时对象虽然已经成为事实上的垃圾对象,但是确不能被发现,进而导致内存泄漏,最终导致内存溢出。但是这种方式简单,只需要维护每个对象被应用的次数就行,但因为其可能会造成内存泄漏,所以并没有得到广泛的应用。

1.2.2:引用追踪

这种方式是通过一组对象出发来标记对象,最终没有被标记的对象就是可回收的垃圾对象,这用来标记对象的一组对象我们叫做GC ROOT,GC ROOT包括如下几类对象:

1:运行中方法的对象
    即虚拟机栈栈帧中本地变量表中的对象引用
2:类的静态成员变量
3:本地方法栈JNI引用的对象

引用追踪通过GC ROOT标记对象的过程需要需要STW,此时程序将会暂停执行,STW的原因是让对象进入一个稳定的状态,这样才能进行正常的标记,避免将正常的对象最终标记为垃圾对象,比如如下程序:

package a.b;

public class WhyStw {
	public static void main(String[] args) {
		Object a = new Object();
	}
}

然后如下编译并查看其字节码:

D:\test>javac -d . WhyStw.java

D:\test>javap -c a.b.WhyStw
Compiled from "WhyStw.java"
public class a.b.WhyStw {
  public a.b.WhyStw();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/lang/Object
       3: dup
       4: invokespecial #1                  // Method java/lang/Object."<init>":()V
       7: astore_1
       8: return
}

其中代码Object a = new Object();创建对象并赋值到变量a的过程指令如下:

0: new           #2                  // class java/lang/Object
3: dup
4: invokespecial #1                  // Method java/lang/Object."<init>":()V
7: astore_1

这里的a就是GC ROOT,因为其是运行中方法的一个对象,但是需要注意这些指令并不是原子的,如果不STW,考虑一种情况,当程序执行到4: invokespecial #1此时只是对象在堆中分配完毕了,但是并没有赋值到局部变量表中的a,因此就有可能被标记为垃圾对象,因此当程序执行7: astore_1时就有可能出现了,当然这只是STW的其中一个原因,应该还有其他原因,欢迎看本文的你在留言中给出自己的理解。

1.2:常见GC算法

常见的GC算法有如下3种:

1:清除算法
2:复制算法
3:整理算法
  • 清除算法
    先标记存活对象,然后删除垃圾对象,如下图:
    在这里插入图片描述

  • 复制算法
    先标记存活对象,然后将对象直接复制到一个新的内存区域,如下图:
    在这里插入图片描述

  • 整理算法
    先标记存活对象,并清除垃圾对象,然后将存活对象移动到内存的一端,如下图:
    在这里插入图片描述

2:常见的GC方式

测试使用的jar包从这里 下载。

2.1:串行GC

即serial GC,使用参数-XX:+UseSerialGC来配置使用串行GC,对于老年代使用的GC收集器是serial old,使用复制算法,对于老年代使用的GC收集器是serial old,采用整理算法,这两种垃圾收集器都是单线程串行方式的,会造成全线的STW,CPU的利用率低,GC时间长,严重降低系统的吞吐量,适用于几百兆小内存的单核机器。

接下来我们实际看下配置串行GC的参数以及其效果,首先运行:

D:\test>java -Xmx1g -Xms1g -XX:-UseAdaptiveSizePolicy -XX:+UseSerialGC -jar test.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.4.RELEASE)

查看GC配置:

C:\WINDOWS\system32>D:\\program_files\\jdk-17.0.1\\bin\\jps
11280 Launcher
19376 test.jar

使用jmap查看堆快照

C:\WINDOWS\system32>jmap -heap 18160
Attaching to process ID 18160, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.202-b08

using thread-local object allocation.
Mark Sweep Compact GC
Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 1073741824 (1024.0MB) -- 最大堆大小1g,即-Xmx1g配置
   NewSize                  = 357892096 (341.3125MB) -- young初始341m
   MaxNewSize               = 357892096 (341.3125MB) -- young最大341m
   OldSize                  = 715849728 (682.6875MB) -- old682m
   NewRatio                 = 2 -- young:old = 1:2
   SurvivorRatio            = 8 -- eden:from:to=8:1:1
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

2.2:并行GC

即parallel GC,这种GC方式会以火力全开的方式来进行垃圾回收,这里火力全开就是用所有的CPU资源,因此这是一种吞吐量优先的GC算法,可以使用如下三种等价的方式的来配置使用parallel GC:

1:-XX:+UseParallelGC
2:-XX:+UseParallelOldGC
3:-XX:+UseParallelGC -XX:+UseParallelOldGC

同样的,并行GC对于年轻代和老年代使用垃圾收集器也不同,对于年轻代使用的垃圾收集器是parallel scavenge,采用复制算法,对于老年代使用的垃圾收集器是parallel old,如果是系统对于吞吐量的要求比较高并且对于相应延迟不敏感,则可以才用并行GC的方式,特别的,如一些后台定时任务则可以优先采用并行GC,尽可能的增加单位时间的吞吐量。

参数-XX:ParallelGCThreads=N来配置执行GC的线程数,默认和核数相等,所以一般该参数可以不用配置。

带来更高的吞吐量,更少的总GC暂停时间,但单次GC暂停时长较长。即GC的总次数少,总时间少,所以吞吐量高,但单次的GC时长长,所以GC时相应延迟大。

接下来我们实际看下配置串行GC的参数以及其效果,首先运行:

D:\test>java -Xmx1g -Xms1g -XX:-UseAdaptiveSizePolicy -XX:+UseParallelGC -jar test.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.4.RELEASE)

查看堆快照:

C:\WINDOWS\system32>jmap -heap 20496
Attaching to process ID 20496, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.202-b08

using thread-local object allocation.
Parallel GC with 10 thread(s) -- 使用并行gc,10个线程

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 1073741824 (1024.0MB)
   NewSize                  = 357564416 (341.0MB)
   MaxNewSize               = 357564416 (341.0MB)
   OldSize                  = 716177408 (683.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

2.3:CMS GC

全称是concurrent mark and sweep garbase collector,通过参数-XX:+UseConcMarkSweepGC参数启用,是一种响应时长优先的垃圾手机策略,年轻代使用复制算法,年老代使用并发清除算法,即年老代不会整理内存空间。通过与应用线程并发的方式来执行GC,为了尽量缩短STW将整个GC过程分为如下6个阶段:

  • 1:初始标记(有STW)
    简单的标记GC ROOT直接引用的对象,以及被年轻代直接引用的对象,有STW,但非常短,如下图:
    在这里插入图片描述

  • 2:并发标记
    从第一步标记的老年代存活对象,开始标记存货对象,此阶段同应用程序一起运行,无stw,如下图:
    在这里插入图片描述

  • 3:并发预处理

  • 4:最终标记
    有stw,完成老年代所有存活对象标记,因为并发标记过程中程序在运行所以会产生新的存活对象,如下图:
    在这里插入图片描述

  • 5:并发清除
    无stw,与应用程序并发执行,删除标记的垃圾对象,并回收其内存空间。

  • 6:并发重置
    重置内部相关变量数据,为下次GC做准备。

CMS垃圾收集器的优点是尽量降低相应延迟,缺点是老年代回收采用删除算法,因此产生内存碎片,并且当堆内存比较大时可能会出现不可预估的长时间GC暂停。

接下来,我们看下CMS GC配置效果:

D:\test>java -Xmx1g -Xms1g -XX:-UseAdaptiveSizePolicy -XX:+UseConcMarkSweepGC -jar test.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.4.RELEASE)

查看堆内存快照:

C:\WINDOWS\system32>jmap -heap 18064
Attaching to process ID 18064, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.202-b08

using parallel threads in the new generation.
using thread-local object allocation.
Concurrent Mark-Sweep GC -- 使用CMS GC

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 1073741824 (1024.0MB) -- 最大堆内存1g
   NewSize                  = 357892096 (341.3125MB) -- 初始年轻代内存341m
   MaxNewSize               = 357892096 (341.3125MB) -- 初始年轻代大小341m
   OldSize                  = 715849728 (682.6875MB) -- 老年代大小682m
   NewRatio                 = 2 -- young:old=1:2
   SurvivorRatio            = 8 -- eden:s0:s1=8:1:1
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB -- 元数据,天文数字,即不限制大小
   G1HeapRegionSize         = 0 (0.0MB)

3:常见的垃圾收集器

常见垃圾收集器如下图:
在这里插入图片描述

4:垃圾收集器的常见组合

如下图:
在这里插入图片描述

serial+serial old对应的配置参数为-XX:+UseSerailGC,低延迟组合parallel new+cms对应的配置参数为-XX:+UseParNewGC-XX:+UseConcMarkSweepGC,高吞吐组合parallel scavenge,parallel old对应的的参数是,-XX:UseParallelGC,-XX:+UseParallelOldGC。详细的可以参考这篇文章 。

写在后面

参考文章列表

如何为你JAVA程序设置最优GC参数?-垃圾回收 。

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

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

相关文章

普源DS1102Z-E示波器,100MHz带宽

DS1000Z-E系列数字示波器是RIGOL基于主流需求而设计的&#xff0c;电商专供款高性能经济型数字示波器,具备100MHz带宽和1GSa/s采样率&#xff0c;搭载RIGOL独创的UltraVision技术平台&#xff0c;更深的储存&#xff08;标配达24 Mpts&#xff09;&#xff0c;高达30,000 wfms/…

解决基于kvm的win10虚拟机只识别2个cpu的问题

在使用kvmqemu创建win10虚拟机的时候&#xff0c;发现尽管我在virt manager里面指定了72个vcpu&#xff0c;但是win10里面只识别2个cpu核心的现象。 如图所示&#xff1a; 虚拟系统管理器里面当时是这样设置的&#xff1a; 这个时候&#xff0c;对应的xml文件内&#xff0c;关…

【深度学习】离线安装Python及相关第三方库

如果对方电脑无法联网。 那么需要在可以联网的电脑上进行如下操作&#xff0c;随后将整个文件包传输到对方电脑&#xff0c;实现环境配置。 Python 先给离线电脑安装Python初始环境 https://www.python.org/downloads/ 这里我选择下载了Python3.7.8 https://www.python.org…

如何用python在微信公众号上添加自己的ChatGPT

由于之前chatgpt的火热&#xff0c;现在很多微信公众号都接入了chatgpt的接口&#xff0c;来给自家公众号增添一丝乐趣&#xff0c;下面我以自己的经验&#xff0c;用python在微信公众上添加自己的chatGPT&#xff0c;先看下方成果图 三步曲 申请自己的公众号部署服务接入chat…

如何用国产DBDesginer软件进行数据库建模设计?

我们在开发软件系统之前都需要进行数据结构的建模设计&#xff0c;传统的都是通过PowerDesiger等国外的软件或直接Excel来进行数据库表结构设计&#xff0c;今天来了解一下如何使用国产软件来进行数据库建模设计 1、首先是注册DBDesigner用户&#xff08; http://dbdesigner.n…

用蹩脚英语在StackOverflow上飞奔:如何在一个RestApi接口中调用另一个RestApi文件接口发送上传文件请求

上班摸鱼、下班干活&#xff0c;日常埋坑、加班填坑——这是我的搬砖&#xff0c;亦是在座的各位&#xff01; 昨天在StackOverflow上面闲逛&#xff0c;突然看到一个国际友人提出了一个问题&#xff0c;他发出了好久都没有人来回答&#xff0c;本着在下为人处世乐善好施、广结…

视频flv怎么转换成mp4格式?

视频flv怎么转换成mp4格式&#xff1f;关于视频格式转换这个问题&#xff0c;小编发现&#xff0c;就算不是从事视频编辑的朋友也有可能经常会遇到这种转换操作&#xff0c;为什么会这样呢&#xff1f;原因主要是因为视频格式的种类真的非常多&#xff0c;多到我们数不清&#…

软件测试之自动化测试

目录 一、初试自动化测试 1.自动化测试的分类&#xff08;简单了解&#xff09; 2.如何实施自动化单元测试 二、selenium 介绍&#xff08;重点内容&#xff09; 1.工作原理 2.Selenium 环境搭建 2.1 Chrome java 2.2 常见问题及解决方案 1.元素的定位 1.1 CSS 定位…

sonarqube分析仓库

sonarqube可以有多种方式分析仓库 使用GitlabCI 设置项目编码 添加环境变量 创建或修改配置文件 sonarqube-check:image: name: sonarsource/sonar-scanner-cli:latestentrypoint: [""]variables:SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defi…

GE H201Ci-1 单通道变压器控制单元

HYDRAN 201Ci-1一个标准模拟输出通道控制器非隔离&#xff0c;跳线可配置为0-l mA 一个遥控电子控制器或4-20 mA&#xff08;最大输出10 V&#xff09;、0-1 V或0-10 V&#xff1b;0-2000 ppm范围 HYDRANR 201Ti智能变送器&#xff1b;它提供网络通信能力 第二个可选模拟输出加…

基于Web的智慧产业园区3D可视化运营管理平台

改革开放以来&#xff0c;园区逐渐成为地区招商引资、储备人才的重要途径。我国社会、经济处于快速发展阶段&#xff0c;园区正向着智慧化、创、科技化转变。 建设背景 在人类的历史发展过程中&#xff0c;随着5G、人工智能、云计算、物联网、GIS等新一轮信息技术的迅速发展&…

Jenkins流水线整合k8s实现代码自动集成和部署

一、前置条件 1、安装好k8s集群 这里先要搭建好一个K8s集群&#xff0c;笔者这边就采用使用了一个一主一丛的k8s集群&#xff0c;k8s集群的版本使用1.19.5版本&#xff0c;服务器的配置&#xff1a;2核4G&#xff0c;操作系统: CentOS Linux release 7.9.2009 (Core) 主机名…

Rabbitmq 下载与安装

文章目录 说明1、下载Erlan2、下载对应的rabbitmq 说明 Rabbitmq依赖于Erlan 对应版本查看&#xff1a;https://www.rabbitmq.com/which-erlang.html 这里版本使用&#xff1a; Rabbitmq 3.9.11 Erlan 24.1.7 1、下载Erlan https://www.erlang.org/patches/otp-24.1.7 安装完…

matlab代码复现:室内定位、无线传感器网路定位、估计优化滤波等探讨及技术支持

室内外定位导航、无线传感器网路定位、估计优化滤波等探讨及技术支持 博主主要擅长以下几个方面&#xff0c;探讨、技术支持、代码复现等问题欢迎联系&#xff0c;也可以站内私信 weixin: ZB823618313&#xff08;备注来意&#xff09; 1. 估计\滤波\融合 1 各种参数估计算法…

ChatGPT智能聊天系统1.0.3版本发布啦~

ChatGPT智能聊天系统1.0.3版本啦&#xff01;主要更新内容如下&#xff1a; 新增功能 获取微信昵称 支付宝支付 PC端允许退出登录 PC端创作和技能支持关键词搜索 分享记录添加今日分享统计 邀请记录添加今日邀请和今日发放统计 细节优化 模型对话框去掉快递发送功能 后…

bioinformatics2022 | Sc2Mol+:使用VAE和Transformer的两阶段基于骨架的分子生成

原文标题&#xff1a;Sc2Mol&#xff1a;a scaffold-based two-step molecule generator with variational autoencoder and transformer 论文地址&#xff1a;Sc2Mol: a scaffold-based two-step molecule generator with variational autoencoder and transformer | Bioinfo…

3 分钟利用 FastGPT 和 Laf 将 ChatGPT 接入企业微信

原文链接&#xff1a;https://forum.laf.run/d/556 FastGPT 是一个超级&#x1f42e;&#x1f37a;的 ChatGPT 平台项目&#xff0c;功能非常强大&#xff1a; ✅ 集成了 ChatGPT、GPT4 和 Claude ✅ 可以使用任意文本来训练自己的知识库、文档库&#xff0c;而且知识库专有模…

无人值守的IDC机房动环综合运维方案

企业数字化转型以及5G、物联网、云计算、人工智能等新业态带动了数据中心的发展&#xff0c;在国家一体化大数据中心及“东数西算”节点布局的推动下&#xff0c;数据中心机房已成为各大企事业单位维持业务正常运营的重要组成部分&#xff0c;网络设备、系统、业务应用数量与日…

16-01 云平台分类和思考

云环境的分类 混合云 为什么选择混合云 混合云网络互联 入口层分流 CDN内容分发网络 CDN工作原理 Captcha图灵测试 SLB软件负载均衡器 SDN&#xff1a;软件定义网络网络层次&#xff1a;通用网络&#xff08;2-4层&#xff09;和HTTP&#xff08;5-7层&#xff09;多种实现…

Espresso Sequencer:针对Rollup生态的Decentralized Shared Sequencing Layer

1. 引言 前序博客&#xff1a; Rollup去中心化Rollup DecentralizationAztec 征集 Rollup Sequencer去中心化提案Espresso Sequencer&#xff1a;去中心化RollupsRadius&#xff1a;针对Rollup生态的Trustless Shared Sequencing层 当前的L2 Rollup方案在扩容的同时&#xf…