03垃圾回收篇(D3_垃圾收集器的选择及相关参数)

目录

学习前言

一、收集器的选择

二、GC日志参数

三、垃圾收集相关的常用参数

四、内存分配与回收策略

1. 对象优先在Eden分配

2. 大对象直接进入老年代

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

4. 动态对象年龄判定

5. 空间分配担保


学习前言

本章主要学习垃圾收集器的选择及相关参数

在实际生产环境上应该如何选择垃圾收集器?相关参数如何设置?

这里只考虑OpenJDK/OracleJDK的HotSpot虚拟机上的垃圾收集器。

没有将Azul和OpenJ9的垃圾收集器加入选择范围,因为不了解。

一、收集器的选择

考虑垃圾收集器的选择时,需要考虑以下事项:

  1. 对于不可能三角(内存占用/吞吐量/延迟),应用的主要功能更关注什么?比如一个OLAP系统,它的大部分功能是各种数据分析和运算,目标是尽快完成计算任务给出结果,那么吞吐量就是主要关注点。而一个OLTP系统,它需要与用户频繁交互,用户频繁地通过页面操作录入数据,那么延迟就是主要关注点。而如果是一个客户端应用或者嵌入式应用,那么内存占用就是主要关注点。
  2. 应用运行的基础设施如何?包括但不限于CPU核数,内存大小?操作系统是Linux还是Windows等等。
  3. 使用的JDK是什么版本?9之前还是9以后?

简单列一个表格,可以参考该表格选择垃圾收集器:

垃圾收集器

关注点

硬件资源

操作系统

JDK版本

优势

劣势

ZGC

低延迟

大内存,很多核

64位操作系统

JDK15以上

延迟真低

需要足够的JVM调试能力;不分代,连续高湾大量内存分配时只能增加堆内存。

Shenandoah

低延迟

大内存,很多核

-

openJDK15以上

延迟很低

需要足够的JNM调试能力;没有ZGC延迅低。

G1

低延迟

4G以上内存,多核

-

JDK9以上

延迟相对较低,技术成熟

内存占用相对其他经典GC较多,延迟低延迟GC受高:

ParNew*CMS

低延迟

4G以下内存,多核

-

JDK9之前

延迟相对较低,技术成熟

已经被抛弃,更大的堆内存比不上G1

Parallel(Scavenge*Old)

吞吐量

-

-

-

吞吐量高

延迟较高

Serial*Serial Old

内存占用

-

-

-

内存占用低,CPU负荷低

延迟高,香吐低

简单总结一下就是,主流的,就做一个普通的JavaWeb,或者微服务中的后台服务,

与用户交互较多,那就根据Java版本来,不是 G1 就是 ParNew+CMS:

  • Java版本在9及9以上,那就无脑选择G1,默认即可;
  • Java版本还是8甚至更老,那就ParNew+CMS;

有点追求的,根据情况来:

  • 有足够的JVM调优能力,且对低延迟有追求,可以尝试ZGC或Shenandoah;
  • 主要做后台单纯数据运算的,比如OLAP,可以尝试Parallel(Scavenge+Old);
  • C/S架构的客户端应用,或者嵌入式应用,可以尝试 Serial+Serail Old。

二、GC日志参数

Java9之前,HotSpot没有统一日志框架,参数比较混乱;Java9之后,所有日志功能都归纳到了 -

Xlog 参数上。

Java9的JVM日志使用方式

-Xlog[:[selector][:[output][:[decorators][:output-options]]]]

说明:

  • selector:选择器,由标签tag和日志级别level组成。标签是功能模块,它指定输出哪个功能模块的日志,GC日志的话,标签就是gc;日志级别从低到高有:Trace、Debug、Info、Warning、Error、Off。
  • decorators:修饰器,指定每行日志的额外输出内容,包括:time,当前时间戳;uptime,VM启动到现在的秒数;timemillis,当前时间毫秒数;uptimemillis,VM启动到现在的毫秒数;timenanos,当前时间纳秒数;uptimenanos,VM启动到现在的纳秒数;pid,进程ID;tid,线程ID;level,日志级别;tags,日志标签。默认是uptime、level和tags。

参考:Java9前后GC相关日志参数对比

功能

Java9及之后

Java9之前

查看GC基本信息

-Xlog;gc

-XX:+PrintGC

查看GC详细信息

-X-log:gc*

-XX:+PrintGCDetails

查看GC前后空间变化

-Xlog:gc+heap=debug

-XX:+PrintHeapAtGC

查看GC中并发时间和停顿时

-Xlog:safepoint

-XX:+Print-GCApplicationConcurrentTime 和

-XX:+PrintGcApplicationstoppedTime

查看GC自适应调节信息

-Xlog:gc+ergo*=trace

-XX:+PrintAdaptive-SizePolicy

查看GC后剩余对象年龄分布

-Xlog:gc+age=trace

-XX:+PrintTenuring-Distribution

还有一个 -verbose:gc 参数,功能与 -Xlog:gc 以及 -XX:+PrintGC 一样。

Java8的 GC 日志的查看,请参考以前的文章:

java8添加并查看GC日志(ParNew+CMS)

三、垃圾收集相关的常用参数

四、内存分配与回收策略

Java技术体系的自动内存管理,最根本的目标是自动化地解决两个问题:自动给对象分配内存以及

自动回收分配给对象的内存。

1. 对象优先在Eden分配

大多数情况下,对象在新生代·Eden区中分配。

当Eden区没有足够空间进行分配时,虚拟机将发起 一次Minor GC。

HotSpot虚拟机提供了-XX:+PrintGCDetails这个收集器日志参数,告诉虚拟机在发生垃圾收集行

为时打印内存回收日志,并且在进程退出的时候输出当前的内存各区域分配情况。

2. 大对象直接进入老年代

大对象就是指需要大量连续内存空间的Java对象,最典型的大对象便是那种很长的字符串,或者元

素数量很庞大的数组,例如:创建一个典型的大对象byte[]数组。

在Java虚拟机中要避免大对象的原因是,在分配空间时,它容易 导致内存明明还有不少空间时就

提前触发垃圾收集,以获取足够的连续空间才能安置好它们,而当复制对象时,大对象就意味着高

额的内存复制开销。

HotSpot虚拟机提供了-XX:PretenureSizeThreshold参数,指定大于该设置值的对象直接在老年代

分配,这样做的目的就是避免在Eden区及两个Survivor区 之间来回复制,产生大量的内存复制操

作。

-XX:PretenureSizeThreshold参数只对Serial和ParNew两款新生代收集器有效,HotSpot的其他

新生代收集器,如Parallel Scavenge并不支持这个参数,如果必须使用此参数进行调优,可考虑

ParNew加CMS的收集器组合。

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

HotSpot虚拟机中多数收集器都采用了分代收集来管理堆内存,那内存回收时就必须能决策哪些存

活对象应当放在新生代,哪些存活对象放在老年代中,为做到这点,虚拟机给每个对象定义了一个

对象年龄(Age)计数器,存储在对象头中。

对象通常在Eden区里诞生,如果经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,

该对象会被移动到Survivor空间中,并且将其对象年龄设为1岁,对象在Survivor区中每熬过一次

Minor GC,年龄就增加1岁,当它的年龄增加到一定程 度(默认为15),就会被晋升到老年代

中。

对象晋升老年代的年龄阈值,可以通过参数-XX:MaxTenuringThreshold设置。

4. 动态对象年龄判定

为了能更好地适应不同程序的内存状况,HotSpot虚拟机并不是永远要求对象的年龄必须达到XX:

MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于

Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到-XX:

MaxTenuringThreshold中要求的年龄。

5. 空间分配担保

在发生Minor GC之前,虚拟机必须先检查老年代最大可用的连续空间是否大于新生代所有对象总

空间,如果这个条件成立,那这一次Minor GC可以确保是安全的,如果不成立,则虚拟机会先查

看XX:

HandlePromotionFailure参数的设置值是否允许担保失败(Handle Promotion Failure);如果允

许,那会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,

如果大于,将尝试进行一次Minor GC,尽管这次Minor GC是有风险的;如果小于,或者-XX:

HandlePromotionFailure设置不允许冒险,那这时就要改为进行一次Full GC。

“冒险”是冒了什么风险:前面提到过,新生代使用复制收集算法,但为了内存利用率, 只使用其中

一个Survivor空间来作为轮换备份,因此当出现大量对象在Minor GC后仍然存活的情况,最极端的

情况就是内存回收后新生代中所有对象都存活,需要老年代进行分配担保,把Survivor无 法容纳的

对象直接送入老年代,这与生活中贷款担保类似。

老年代要进行这样的担保,前提是老年代 本身还有容纳这些对象的剩余空间,但一共有多少对象

会在这次回收中活下来在实际完成内存回收之 前是无法明确知道的,所以只能取之前每一次回收

晋升到老年代对象容量的平均大小作为经验值,与 老年代的剩余空间进行比较,决定是否进行Full

GC来让老年代腾出更多空间。

取历史平均值来比较其实仍然是一种赌概率的解决办法,也就是说假如某次Minor GC存活后的对

象突增,远远高于历史平均值的话,依然会导致担保失败。如果出现了担保失败,那就只好老老实

实 地重新发起一次Full GC,这样停顿时间就很长了。

虽然担保失败时绕的圈子是最大的,但通常情况下 都还是会将-XX:HandlePromotionFailure开关

打开,避免Full GC过于频繁。

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

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

相关文章

Hadoop特点和HDFS命令

Hadoop的特点 高扩展性: 可以根据数据量的增长进行扩展,可以扩展到数千台机器,每个机器都可以提供本地计算和存储资源 高容错性: 自动保存数据的多个副本,并能够在硬件故障的情况下重新分配计算任务,从而确保系统的高可用性和数据的不丢失。…

LetsWave脑电数据简单ERP分析matlab(一)

LetsWave是基于matlab的一款工具包,类似eeglab,也可以对数据进行预处理。习惯使用eeglab做数据预处理的,可以先在eeglab中做预处理,然后可以保存为*.set格式,最后在letswave中画图。 letswave下载地址:htt…

深度学习|表示学习|卷积神经网络|通道 channel 是什么?|05

如是我闻: 在卷积神经网络(CNN)中,channel(通道) 是指输入或输出数据的深度维度,通常用来表示输入或输出的特征类型。 通道的含义 输入通道(Input Channels):…

【机器学习】机器学习引领数学难题攻克:迈向未知数学领域的新突破

我的个人主页 我的领域:人工智能篇,希望能帮助到大家!!!👍点赞 收藏❤ 一、引言 在数学的浩瀚领域中,存在着诸多长期未解的难题,这些难题犹如高耸的山峰,吸引着无数数…

2024年美赛C题评委文章及O奖论文解读 | AI工具如何影响数学建模?从评委和O奖论文出发-O奖论文做对了什么?

模型假设仅仅是简单陈述吗?允许AI的使用是否降低了比赛难度?还在依赖机器学习的模型吗?处理题目的方法有哪些?O奖论文的优点在哪里? 本文调研了当年赛题的评委文章和O奖论文,这些问题都会在文章中一一解答…

Ubuntu如何安装redis服务?

环境: Ubuntu22.04 WSL2 问题描述: 如何安装redis服务? 解决方案: 1.在 Linux 上(如 Ubuntu/Debian)安装 1.通过包管理工具安装 Redis 服务器: sudo apt update sudo apt install redis…

最新-CentOS 7安装1 Panel Linux 服务器运维管理面板

CentOS 7安装1 Panel Linux 服务器运维管理面板 一、前言二、环境要求三、在线安装四、离线安装1.点击下面1 Panel官网链接访问下载,如未登录或注册,请登录/注册后下载2.使用将离线安装包上传至目标终端/tem目录下3.进入到/tem目录下解压离线安装包4.执行…

Centos类型服务器等保测评整/etc/pam.d/system-auth

修改服务器配置文件/etc/pam.d/system-auth,但是,把一下配置放在password的配置第一行才会生效 执行命令:配置口令要求:大小写字母、数字、特殊字符组合、至少8位,包括强制设置root口令! sed -i 14a pas…

OSCP - Proving Grounds - Quackerjack

主要知识点 端口转发 具体步骤 执行nmap扫描,开了好多端口,我先试验80和8081,看起来8081比较有趣 Nmap scan report for 192.168.51.57 Host is up (0.0011s latency). Not shown: 65527 filtered tcp ports (no-response) PORT STATE SERVICE …

日志收集Day005

1.filebeat的input类型之filestream实战案例: 在7.16版本中已经弃用log类型,之后需要使用filebeat,与log不同,filebeat的message无需设置就是顶级字段 1.1简单使用: filebeat.inputs: - type: filestreamenabled: truepaths:- /tmp/myfilestream01.lo…

9.中断系统、EXTI外部中断

中断系统原理 中断 中断系统是管理和执行中断的逻辑结构,外部中断是众多能产生中断的外设之一,所以本节我们就借助外部中断来学习一下中断系统。在以后学习其它外设的时候,也是会经常和中断打交道的。 中断:在主程序运行过程中…

Java如何实现反转义

Java如何实现反转义 前提 最近做的一个需求,是热搜词增加换一批的功能。功能做完自测后,交给了测试伙伴,但是测试第二天后就提了一个bug,出现了未知词 levis。第一眼看着像公司售卖的一个品牌-李维斯。然后再扒前人写的代码&…

[STM32 - 野火] - - - 固件库学习笔记 - - -十一.电源管理系统

一、电源管理系统简介 电源管理系统是STM32硬件设计和系统运行的基础,它不仅为芯片本身提供稳定的电源,还通过多种电源管理功能优化功耗、延长电池寿命,并确保系统的可靠性和稳定性。 二、电源监控器 作用:保证STM32芯片工作在…

js学习笔记(2)

一、函数 1.JavaScript 函数语法 函数就是包裹在花括号中的代码块,前面使用了关键词 function: function functionname() {// 执行代码 } 当调用该函数时,会执行函数内的代码。 可以在某事件发生时直接调用函数(比如当用户点…

自动驾驶之DriveMM: All-in-One Large Multimodal Model for Autonomous Driving

1. 写在前面 工作之后,主要从事于偏工程比较多的内容, 很少有机会读论文了,但2025年,由于之前有些算法的背景, 后面可能会接触一些多模态大模型相关的工作,所以又调头有点往算法的方向偏移, 而算法呢,很重要的一点就是阅读论文。2025年,再拾起论文这块的工作。 今天…

机器学习-数据集划分

文章目录 一. 为什么要划分数据集二. 数据集划分的方法1. 留出法:2. 交叉验证:将数据集划分为训练集,验证集,测试集3. 留一法:4. 自助法: 一. 为什么要划分数据集 为了能够评估模型的泛化能力,可…

最新-CentOS 7 基于1 Panel面板安装 JumpServer 堡垒机

CentOS 7 基于1 Panel面板安装 JumpServer 堡垒机 一、前言二、设备要求三、环境要求四、安装4.1 环境安装4.2 JumpServer安装4.3 访问JumpServerWeb端,进行登录 五、登录Web控制台 一、前言 JumpServer是广受欢迎的开源堡垒机。运维必备神器!JumpServe…

解决CentOS9系统下Zabbix 7.2图形中文字符乱码问题

操作系统:CentOS 9 Zabbix版本:Zabbix7.2 问题描述:主机图形中文字符乱码 解决方案: # 安装字体配置和中文语言包 sudo yum install -y fontconfig langpacks-zh_CN.noarch # 检查是否已有中文字体: fc-list :lan…

JAVA-快速排序

一、快速排序基本思想 快速排序是 Hoare 于 1962 年提出的一种二叉树结构的交换排序方法,其基本思想为: 任取待排序元素序列中的某元 素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值&#…

WPF1-从最简单的xaml开始

1. 最简单的WPF应用 1.1. App.config1.2. App.xaml 和 App.xaml.cs1.3. MainWindow.xaml 和 MainWindow.xaml.cs 2. 正式开始分析 2.1. 声明即定义2.2. 命名空间 2.2.1. xaml的Property和Attribute2.2.2. xaml中命名空间2.2.3. partial关键字 学习WPF,肯定要先学…