JVM虚拟机系统性学习-JVM调优实战之内存溢出、高并发场景调优

调优实战-内存溢出的定位与分析

首先,对于以下代码如果造成内存溢出该如何进行定位呢?通过 jmapMAT 工具进行定位分析

代码如下:

public class TestJvmOutOfMemory {public static void main(String[] args) {List<Object> list = new ArrayList<>();for (int i = 0; i < 10000000; i++) {StringBuilder str = new StringBuilder();for (int j = 0; j < 1000; j++) {str.append(UUID.randomUUID().toString());}list.add(str.toString());}System.out.println("ok");}
}

设置虚拟机参数如下:

-Xms8m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

再执行上边代码,发现执行之后,发生了内存溢出,并且在当前项目的目录下产生了 java_pid520944.hprof 文件

使用 MAT 工具分析

在 https://eclipse.dev/mat/downloads.php 中下载 MAT 工具,MAT 工具就是用于分析 Java 堆内存的,可以查看内存泄漏以及内存使用情况

在这里插入图片描述

下载解压之后,点击 exe 文件启动 MAT 工具,将生成的 hprof 文件拖入即可,那么通过 MAT 工具可以看到

调优实战-高并发场景调优

首先,说明一下业务场景,系统主要与用户交互,并且主要是提供 API 服务,因此对于系统延时比较敏感,存在的问题为,发现该系统在高峰期延时过高,通过监控平台发现以下问题:

  • Young GC 比较频繁,每 10 分钟有 50-60 次,峰值达到 400 次
  • Full GC 比较频繁,每 1 个小时平均一次,峰值为 10 分钟 5 次

那么首先排除代码层面的问题,之后再来看 JVM 参数配置所存在的问题,项目使用 JDK8,调优前 JVM 参数如下:

# 设置了堆大小为 4G,新生代大小为 1G
-Xms4096M -Xmx4096M -Xmn1024M
# 设置了永久代大小为 512M,但是并不会生效,因为 JDK8 中使用元空间来实现方法区,永久代已经不使用了,因此下边这两个参数没有起作用
-XX:PermSize=512M
-XX:MaxPermSize=512M
存在问题

问题1:未设置垃圾回收器

从配置的 JVM 参数中可以看到,并未指定使用的垃圾回收器,在 JDK8 中默认使用的垃圾回收器为:(可以在命令行通过 java -XX:+PrintCommandLineFlags -version 来查看 JDK 默认的一些配置信息)

  • 年轻代使用 Parallel Scavenge
  • 老年代使用 Parallel Old

这个组合的垃圾回收器是以 吞吐量优先 的,适合于后台任务型服务器,但是当前服务是与用户进行交互的,因此需要使用 低延迟优先 的垃圾回收器

问题2:年轻代分配不合理

当前系统主要是向外提供 API,那么系统中大多数对象的生命周期都是比较短的,通过 Young GC 都可以进行回收,但是目前的 JVM 配置给堆空间分配了 4G,新生代只有 1G,而新生代又分为 Eden 和 Survivor 区,因此新生代有效大小为 Eden + 一个 Survivor 区,也就是 0.9 G

那么在服务高负载的情况下,新生代中的 Eden + Survivor 区会迅速被占满,进而导致频繁 Young GC,还会引起本应该被 Young GC 回收的垃圾提前晋升到老年代中,导致 Full GC 的频率增加,老年代使用的 Parallel Old 无法与用户线程并发执行进行垃圾回收,因此 STW 时间比较长

问题3:未设置元空间大小

调优前设置了永久代大小,但是 JDK8 中已经废弃了永久代,因此设置永久代大小无效

对于 JDK8 来说,如果不指定元空间的大小,在 64 位操作系统中,默认元空间初始值为 21MB,默认元空间的最大值是系统内存的大小,初始未给定的元空间的大小,因此元空间初始为 21MB,导致 频繁触发 Full GC 来扩张元空间大小

优化方案

首先,针对垃圾回收器,常用的组合如下:

  • Parallel Scavenge + Parallel Old:吞吐量优先,适合后台任务型服务
  • ParNew + CMS:低延迟优先,适合对延迟时间比较敏感的服务
  • G1:JDK9 默认垃圾回收器,兼顾了高吞吐量和低延迟
  • ZGC:JDK11 中退出的低延迟垃圾回收器,无论堆空间多大,都可以保证低延迟

因此,对于目前的系统选择 ParNew + CMS 的组合

而元空间大小的设置,可以通过监控查看元空间峰值为多少,也可以通过命令 jstat -gc [进程id] 查看元空间占用在 150MB 左右,因此可以将元空间大小设置为 256MB

对于年轻代的设置,我们可以考虑在堆空间大小不变的情况下,将新生代空间扩展为 0.5 ~ 1 倍,可以分别扩展 0.5 倍、1 倍,再对扩展后的应用进行压测分析,来选择表现性能更好的方案,这里我们就将年轻代扩展 0.5 倍

优化后的参数设置如下:

# 新生代扩展 0.5 倍
-Xms4096M -Xmx4096M -Xmn1536M
# 初始元空间大小设置为 256M
-XX:MetaspaceSize=256M
-XX:MaxMetaspaceSize=256M
# 使用 ParNew + CMS 垃圾回收器
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
# CMS 在重新标记阶段,会暂停用户线程,重新扫描堆中的对象,进行可达性分析,标记活着的对象,因为并发阶段 GC 线程和用户线程是并发执行的,可能有些对象的状态会因为用户线程的执行而变化,因此在重新标记节点需要进行标记修正,重新标记阶段会以新生代中的对象作为 GC Roots 的一部分,通过开启下边这个参数会在重新标记之前先执行一次 YoungGC 可以回收掉大部分的新生代对象,从而减少扫描 GC Roots 的开销
-XX:+CMSScavengeBeforeRemark
优化方案发布

通过灰度发布,选择部分实例上线,当线上实例指标符合预期之后,再进行全量升级

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

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

相关文章

C#学习笔记

static viod Main(string[] args) {Console.WriteLine(“Hello,word!”); Console.ReadKey(); //停留弹窗 } static 静态 void 无返回值 Main 函数 - 程序起点 2.2 命名空间及标识符、关键字 namespace 别名使用 取别名:using Co = System.Console; 使用:Co.WriteLine(“H…

Python | 高斯分布拟合示例

什么是正态分布或高斯分布&#xff1f; 当我们绘制一个数据集&#xff08;如直方图&#xff09;时&#xff0c;图表的形状就是我们所说的分布。最常见的连续值形状是钟形曲线&#xff0c;也称为高斯分布或正态分布。 它以德国数学家卡尔弗里德里希高斯的名字命名。遵循高斯分布…

git的介绍

Git 是一个分布式版本控制系统&#xff0c;用于跟踪代码的更改并协同开发。它具有以下基本概念和使用方式&#xff1a; 仓库&#xff08;Repository&#xff09;&#xff1a;Git 仓库是存储代码的地方。它可以是本地仓库&#xff08;位于开发者的计算机上&#xff09;或远程仓库…

Positive Technologies 专家总结了调查结果,并指出了 2023 年信息安全威胁发展的主要趋势

Positive Technologies 专家总结了调查结果&#xff0c;并指出了 2023 年信息安全威胁发展的主要趋势 &#x1f977; 间谍软件最流行 在攻击俄罗斯组织时使用的所有恶意软件中&#xff0c;间谍软件所占比例接近一半&#xff08;45%&#xff09;&#xff0c;加密软件仅占 27%。…

Vue学习笔记-Vue3中的provide与inject

作用 provide和inject用于实现祖孙间的数据通信 用法 导入&#xff1a;import {provide,inject} from vue 使用&#xff1a; provide&#xff1a;祖组件使用该方法提供数据&#xff08;可以给任意后代组件&#xff0c;但一般用于孙组件及其后代组件&#xff0c;因为父子间的…

算法通关村第十二关—字符串转换(青铜)

一、转换成小写字母 LeetCode709.给你一个字符串s&#xff0c;将该字符串中的大写字母转换成相同的小写字母&#xff0c;返回新的字符串。 示例1&#xff1a; 输入&#xff1a;s"Hello" 输出&#xff1a;"hello" 示例2&#xff1a; 输入&#xff1a;s&qu…

C语言——输出魔方阵

目录 一、前言&#xff1a; 二、算法设计&#xff1a; 三、代码实现&#xff1a; 五、效果展示&#xff1a; 一、前言&#xff1a; 魔方矩阵又称幻方&#xff0c;是有相同的行数和列数&#xff0c;并在每行每列、对角线上的和都相等的矩阵。魔方矩阵中的每个元素不能相同。你…

算法通关村第十九关 | 青铜 | 动态规划

1.统计路径总数&#xff08;递归&#xff09; 原题&#xff1a;力扣62. 每次移动都是将问题规模缩小。 要理解&#xff1a;return search(m - 1, n) search(m, n - 1); public class Solution {public int uniquePaths (int m, int n) {return search(m, n);}public int s…

外包干了4个月,测试技术退步明显

先说一下自己的情况&#xff0c;本科生&#xff0c;20年通过校招进入杭州某软件公司&#xff0c;干了3年的功能测试&#xff0c;当然有半年是被封在了家里&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我…

牛客网BC107矩阵转置

答案&#xff1a; #include <stdio.h> int main() {int n0, m0,i0,j0,a0,b0;int arr1[10][10]{0},arr2[10][10]{0}; //第一个数组用来储存原矩阵&#xff0c;第二个数组用来储存转置矩阵scanf("%d%d",&n,&m); if((n>1&&n<10)&&am…

LRU算法(面试遇到两次)

原理&#xff1a; 最近最久未使用&#xff08;Least Recently Used LRU&#xff09;算法是⼀种缓存淘汰策略。如果新存入或者访问一个值&#xff0c;则将这个值放在队列开头。如果存储容量超过上限cap&#xff0c;那么删除队尾元素&#xff0c;再存入新的值。新插入的元素…

【学习】卡尔曼滤波

【精 | 有代码】卡尔曼滤波器的直观介绍和手写代码&#xff01; 卡尔曼滤波器的直观介绍&#xff08;第 1 部分&#xff09;: https://www.youtube.com/watch?v5Y-dnt2tNKY 【手写代码一步步展示&#xff01;精&#xff01;强推&#xff01;】Coding Kalman Filter in Pytho…

jmeter,断言:响应断言、Json断言

一、响应断言 接口A请求正常返回值如下&#xff1a; {"status": 10013, "message": "user sign timeout"} 在该接口下创建【响应断言】元件&#xff0c;配置如下&#xff1a; 若断言成功&#xff0c;则查看结果树的接口显示绿色&#xff0c;若…

RocketMQ源码 Broker-TopicConfigManager 元数据管理组件源码分析

前言 ConsumerOffsetManager负责管理Broker端的topicConfig元数据信息&#xff0c;它继承了ConfigManager组件&#xff0c;且定时将内存中维护的topic元数据信息&#xff0c;注册到远程NameServer集群&#xff0c;并持久化到磁盘文件。 源码版本&#xff1a;4.9.3 源码架构图…

12.15

写这段代码改了好几个小时&#xff0c;从有这个想法到完成花费了比较久的时间&#xff0c;也很有成就感。速成课给的伪代码思路漏掉了需要判断最小数是否正好是这个数本身这个条件&#xff0c;所以一直报错。所以写代码要把每种可能性都涵盖&#xff0c;不然程序就会出问题。之…

【渗透测试】常用的8种火狐插件

1、Max HacKBar 推荐理由&#xff1a;免费的hackbar插件&#xff0c;可快速使用SQL注入、XSS和Bypass等payload进行测试&#xff0c;可进行多种编码和解码&#xff0c;安装后F12即可使用。 2、FoxyProxy Standard 推荐理由&#xff1a;FoxyProxy是一个高级的代理管理工具&am…

jmeter,csv文件参数化+断言 实现一个接口的case

1、case 及其 测试数据 注意保存文件的编码格式 id,name,limit,status,address,start_time,assert_status,assert_message 100,小米100,1000,1,某某会展中心101,2023-8-20 14:20,200,add event success ,,,,,,10021,parameter error 100,小米102,1002,1,某某会展中心103,2023-…

十五、YARN辅助架构

1、学习内容 &#xff08;1&#xff09;了解什么是代理服务器 &#xff08;2&#xff09;了解什么是历史服务器 2、辅助架构 &#xff08;1&#xff09;辅助架构的由来 对于YARN架构来讲&#xff0c;除了ResourceManager集群资源总管家、NodeManager单机资源管家两个核心角…

AI日报:谷歌Gemini Pro即将面向企业和开发者

文章目录 总览Gemini介绍 模型能力产品API其他产品Imagen2和其他新闻Duet AI 总览 现在&#xff0c;您可以免费访问Gemini Pro的API&#xff0c;这是谷歌最新大型语言模型的第一个版本。 Gemini 介绍 谷歌通过其API让企业和开发者第一次看到了其最强大的大型语言模型Gemini。…

后端项目操作数据库-中枢组件Service调用Mapper实现增删改查-实例

接上篇 使用MyBatis配置Mapper实现增删改查 1.Service的基本作用 Service在代码中的的作用是调用Mapper、被Controller调用。是后端项目中非常重要的组件。 用于设计业务流程、业务逻辑&#xff0c;以保障数据的完整性、有效性、安全性。 2. Service使用举例——“添加相册”…