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

news/2024/6/17 15:59:48 标签: 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.niftyadmin.cn/n/5265381.html

相关文章

powershell执行策略不受限制

powershell执行策略不受限制 powershell nodemon 1.以管理员身份运行powershell。 2.运行以下命令 Set-ExecutionPolicy Unrestricted AllSigned 脚本可以运行。 要求所有脚本和配置文件都由受信任的发布者签名&#xff0c;包括在本地计算机上编写的脚本。 在从尚未分类为受信…

四六级高频词组12

目录 词组 其他链接 词组 501. &#xff08;a&#xff09; passion for 对…的热爱&#xff0c;热情 502. be patient with 对…耐心 503. pay for 赔偿&#xff0c; 付款&#xff0c; 报偿&#xff0c; 处罚 504. pay…for 付…的钱 505. &#xff08;be&#xff09; …

20.Java程序设计-基于SSM框架的安卓掌上校园生活系统的设计与实现

摘要&#xff1a; 随着移动互联网技术的快速发展&#xff0c;校园生活信息化成为提高学校管理效率、方便学生生活的关键。本研究以基于SSM&#xff08;Spring Spring MVC MyBatis&#xff09;框架的技术体系为基础&#xff0c;致力于设计与实现一款功能强大、高效稳定的安卓…

常用数据库的分页语句(mySlq、oracle、PostgreSQL、SQL Server)

目录 ORACLE MySQL PostgreSQL SQL Server ORACLE SELECT * FROM (SELECT t.*, ROWNUM AS rnFROM (SELECT * FROM 表名 ORDER BY 排序字段) tWHERE ROWNUM < 结束行数 ) WHERE rn > 开始行数; 其中&#xff0c;表名是你要查询的表名&#xff0c;排序字段是你希望按…

「完美世界」石昊被诓入至尊道场,修炼无敌道,打跑天仙书院弟子

Hello,小伙伴们&#xff0c;我是拾荒君。 《完美世界》这部国漫&#xff0c;在粉丝的翘首期盼中&#xff0c;终于迎来了第141集的更新。这一集的内容&#xff0c;对于喜欢石昊和至尊道场劫难的观众来说&#xff0c;可谓是扣人心弦&#xff0c;让人目不转睛。 在这一集中&#…

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-…

K8s可视化kuboard 部署

创建资产 [rootkube-master ~]# kubectl apply -f https://addons.kuboard.cn/kuboard/kuboard-v3.yaml 查看对应资源 [rootkube-master ~]# kubectl get pod -n kuboard NAME READY STATUS RESTARTS AGE kuboard-agent-2-5c4f886…

区块链的可扩展性研究【06】Plasma

1.Plasma&#xff1a;Plasma 是一种基于以太坊区块链的 Layer2 扩容方案&#xff0c;它通过建立一个分层结构的区块链网络&#xff0c;将大量的交易放到子链上进行处理&#xff0c;从而提高了以太坊的吞吐量。Plasma 还可以通过智能合约实现跨链交易&#xff0c;使得不同的区块…