13-JVM调优实战-3

news2025/1/12 21:04:47

上一篇:12-JVM调优实战-2

今天来介绍一款阿里巴巴的调优工具。

Arthas详解

Arthas 是 Alibaba 在 2018 年 9 月开源的 Java 诊断工具。支持 JDK6+, 采用命令行交互模式,可以方便的定位和诊断线上程序运行问题。Arthas 官方文档十分详细,详见:https://alibaba.github.io/arthas

1.Arthas使用场景

得益于 Arthas 强大且丰富的功能,让 Arthas 能做的事情超乎想象。下面仅仅列举几项常见的使用情况,更多的使用场景可以在熟悉了 Arthas 之后自行探索。

  1. 是否有一个全局视角来查看系统的运行状况?
  2. 为什么 CPU 又升高了,到底是哪里占用了 CPU ?
  3. 运行的多线程有死锁吗?有阻塞吗?
  4. 程序运行耗时很长,是哪里耗时比较长呢?如何监测呢?
  5. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
  6. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
  7. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
  8. 有什么办法可以监控到 JVM 的实时运行状态?

2.Arthas使用

# github下载arthas
wget https://alibaba.github.io/arthas/arthas-boot.jar
# 或者 Gitee 下载
wget https://arthas.gitee.io/arthas-boot.jar

用java -jar运行即可,可以识别机器上所有Java进程(我们这里之前已经运行了一个Arthas测试程序,代码见下方)
在这里插入图片描述

package com.gwx.jvm;

import java.util.HashSet;

public class Arthas {

    private static HashSet hashSet = new HashSet();

    public static void main(String[] args) {
        // 模拟 CPU 过高
        cpuHigh();
        // 模拟线程死锁
        deadThread();
        // 不断的向 hashSet 集合增加数据
        addHashSetThread();
    }

    /**
     * 不断的向 hashSet 集合添加数据
     */
    public static void addHashSetThread() {
        // 初始化常量
        new Thread(() -> {
            int count = 0;
            while (true) {
                try {
                    hashSet.add("count" + count);
                    Thread.sleep(1000);
                    count++;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public static void cpuHigh() {
        new Thread(() -> {
            while (true) {

            }
        }).start();
    }

    /**
     * 死锁
     */
    private static void deadThread() {
        /** 创建资源 */
        Object resourceA = new Object();
        Object resourceB = new Object();
        // 创建线程
        Thread threadA = new Thread(() -> {
            synchronized (resourceA) {
                System.out.println(Thread.currentThread() + " get ResourceA");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + "waiting get resourceB");
                synchronized (resourceB) {
                    System.out.println(Thread.currentThread() + " get resourceB");
                }
            }
        });

        Thread threadB = new Thread(() -> {
            synchronized (resourceB) {
                System.out.println(Thread.currentThread() + " get ResourceB");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + "waiting get resourceA");
                synchronized (resourceA) {
                    System.out.println(Thread.currentThread() + " get resourceA");
                }
            }
        });
        threadA.start();
        threadB.start();
    }
}

选择进程序号1,进入进程信息操作
在这里插入图片描述

输入dashboard可以查看整个进程的运行情况,线程、内存、GC、运行环境信息:
在这里插入图片描述

输入thread可以查看线程详细情况
在这里插入图片描述

输入 thread加上线程ID 可以查看线程堆栈
在这里插入图片描述

输入 thread -b 可以查看线程死锁
在这里插入图片描述

输入 jad加类的全名 可以反编译,这样可以方便我们查看线上代码是否是正确的版本
在这里插入图片描述

使用 ognl 命令可以
在这里插入图片描述

更多命令使用可以用help命令查看,或查看文档:https://arthas.aliyun.com/doc/commands.html

3.GC日志详解

对于java应用我们可以通过一些配置把程序运行过程中的gc日志全部打印出来,然后分析gc日志得到关键性指标,分析GC原因,调优JVM参数。
打印GC日志方法,在JVM参数里增加参数,%t 代表时间

-Xloggc:./gc-%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps  -XX:+PrintGCTimeStamps -XX:+PrintGCCause  
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M

Tomcat则直接加在JAVA_OPTS变量里。

3.1.如何分析GC日志

运行程序加上对应gc日志

java -jar -Xloggc:./gc-%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps  -XX:+PrintGCTimeStamps -XX:+PrintGCCause  
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M microservice-eureka-server.jar

下图中是我截取的JVM刚启动的一部分GC日志
在这里插入图片描述

我们可以看到图中第一行红框,是项目的配置参数。这里不仅配置了打印GC日志,还有相关的VM内存参数。
第二行红框中的是在这个GC时间点发生GC之后相关GC情况。

  1. 对于2.909: 这是从jvm启动开始计算到这次GC经过的时间,前面还有具体的发生时间日期。
  2. Full GC(Metadata GC Threshold)指这是一次full gc,括号里是gc的原因, PSYoungGen是年轻代的GC,ParOldGen是老年代的GC,Metaspace是元空间的GC
  3. 6160K->0K(141824K),这三个数字分别对应GC之前占用年轻代的大小,GC之后年轻代占用,以及整个年轻代的大小。
  4. 112K->6056K(95744K),这三个数字分别对应GC之前占用老年代的大小,GC之后老年代占用,以及整个老年代的大小。
  5. 6272K->6056K(237568K),这三个数字分别对应GC之前占用堆内存的大小,GC之后堆内存占用,以及整个堆内存的大小。
  6. 20516K->20516K(1069056K),这三个数字分别对应GC之前占用元空间内存的大小,GC之后元空间内存占用,以及整个元空间内存的大小。
  7. 0.0209707是该时间点GC总耗费时间。

从日志可以发现几次fullgc都是由于元空间不够导致的,所以我们可以将元空间调大点

java -jar -Xloggc:./gc-adjust-%t.log -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+PrintGCDetails -XX:+PrintGCDateStamps  
-XX:+PrintGCTimeStamps -XX:+PrintGCCause  -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M 
microservice-eureka-server.jar

调整完我们再看下gc日志发现已经没有因为元空间不够导致的fullgc了

对于CMS和G1收集器的日志会有一点不一样,也可以试着打印下对应的gc日志分析下,可以发现gc日志里面的gc步骤跟我们之前讲过的步骤是类似的

public class HeapTest {

    byte[] a = new byte[1024 * 100];  //100KB

    public static void main(String[] args) throws InterruptedException {
        ArrayList<HeapTest> heapTests = new ArrayList<>();
        while (true) {
            heapTests.add(new HeapTest());
            Thread.sleep(10);
        }
    }
}

CMS

-Xloggc:d:/gc-cms-%t.log -Xms50M -Xmx50M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+PrintGCDetails -XX:+PrintGCDateStamps  
 -XX:+PrintGCTimeStamps -XX:+PrintGCCause  -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M 
 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC   

G1

-Xloggc:d:/gc-g1-%t.log -Xms50M -Xmx50M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+PrintGCDetails -XX:+PrintGCDateStamps  
 -XX:+PrintGCTimeStamps -XX:+PrintGCCause  -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -XX:+UseG1GC 

上面的这些参数,能够帮我们查看分析GC的垃圾收集情况。但是如果GC日志很多很多,成千上万行。就算你一目十行,看完了,脑子也是一片空白。所以我们可以借助一些功能来帮助我们分析,这里推荐一个gceasy(https://gceasy.io),可以上传gc文件,然后他会利用可视化的界面来展现GC情况。具体下图所示

在这里插入图片描述

上图我们可以看到年轻代,老年代,以及永久代的内存分配,和最大使用情况。
在这里插入图片描述

上图我们可以看到堆内存在GC之前和之后的变化,以及其他信息。
这个工具还提供基于机器学习的JVM智能优化建议,当然现在这个功能需要付费(其实,你把语言切换为:中文,就免费啦,世界如此简单,哈哈哈
在这里插入图片描述

4.JVM参数汇总查看命令

# 表示打印出所有参数选项的默认值
java -XX:+PrintFlagsInitial 
# 表示打印出所有参数选项在运行程序时生效的值
java -XX:+PrintFlagsFinal 

下一篇:

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

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

相关文章

【驱动开发】实现三盏灯的控制,编写应用程序测试

head.h #ifndef __HEAD_H__ #define __HEAD_H__//LED1:PE10 //LED2:PF10 //LED3:PE8#define LED_RCC 0X50000A28 //使能GPIO#define LED_MODER 0X50006000 //设置输出模式 #define LED_ODR 0X50006014 //设置输出高低电平#define LED2_MODER 0X50007000 …

一款 IDEA 插件帮你优雅转化 DTO、VO、BO、PO、DO

转自&#xff1a;码猿技术专栏 POJO 的定义是无规则简单的对象&#xff0c;在日常的代码分层中 pojo 会被分为VO、BO、 PO、 DTO VO &#xff08;view object/value object&#xff09;表示层对象 1、前端展示的数据&#xff0c;在接口数据返回给前端的时候需要转成VO 2、个…

火山引擎DataLeap的数据血缘用例与设计概述

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 数据血缘描述了数据的来源和去向&#xff0c;以及数据在多个处理过程中的转换。数据血缘是组织内使数据发挥价值的重要基础能力。本文从字节的数据链路概况开始&…

开学季,长沙又一次戳中年轻人:人才巴士,欢迎“星”同学

初秋临近&#xff0c;又是一年开学季。与往年不一样的是&#xff0c;当数以万计的学子从全国各地来到长沙&#xff0c;这座年轻人友好的城市也用独特的方式表达着对新生的欢迎与诚意&#xff1a;24辆人才巴士“穿上”欢迎词&#xff1b;60个公交站台向新生“表白”&#xff1b;…

linux一些常用的下载工具-aria2

从断点续传开始 故事的过程是这样的&#xff0c;朋友是搞科研的&#xff0c;需要在一个国外的学术网站下载一个药物的模型压缩包&#xff0c;大概有23g。关键他也不会用别的就wget下载…恩中间还断了…问我有什么方法没有断点续传&#xff0c;而是能不能更快速的下载&#xff…

实用工具JRebel XRebel【2023】配置和使用的详解

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于JRebel & XRebel的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.JRebel 的简介 二.插件的…

03深度学习-目标检测-深度学习方法与传统算法对比

一、目标学习的检测方法变迁及对比 “目标检测“是当前计算机视觉和机器学习领域的研究热点。从Viola-Jones Detector、DPM等冷兵器时代的智慧到当今RCNN、YOLO等深度学习土壤孕育下的GPU暴力美学&#xff0c;整个目标检测的发展可谓是计算机视觉领域的一部浓缩史。整个目标…

【算法与数据结构】236、LeetCode二叉树的最近公共祖先

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a; 根据定义&#xff0c;最近祖先节点需要遍历节点的左右子树&#xff0c;然后才能知道是否为最近祖先节…

【ccf-csp题解】第0次csp认证-第四题-有趣的数-组合数学

题目描述 思路说明 本题涉及组合数学的知识 目的是在n个空位上放置0、1、2、3&#xff0c;问符合题意的放法有多少种 首先注意到一个重要的事实&#xff1a; 只要0和1的位置已经确定&#xff0c;那么2和3的摆放就十分容易了 那么把所有情况分为n-2种&#xff1a; 第一种…

IntelliJ IDEA 配合 Maven 的一些技巧(prifiles)

环境 IntelliJ IDEA 2017.1 Maven 3.3.9 Nexus 3.2.1 学习前提 了解 Maven 配置的基本用法 了解私有仓库&#xff0c;比如 nexus 的一些概念 强烈建议把 Maven 的 settings.xml 文件同时放在&#xff1a;%USER_HOME%/.m2/settings.xml 和 ${maven.home}/conf/settings.xm…

给 Ubuntu 操作系统配置静态 IP

针对 Ubuntu 22.04.3 操作系统的静态 IP 配置 一、查看初始的网络信息 查看网卡名称 ifconfig查看网关信息 route -n二、编辑网络配置文件 编辑文件&#xff0c;配置文件的名称可能不一样&#xff0c;自己去 /etc/netplan/ 目录查看 sudo vim /etc/netplan/01-network-manager-…

51单片机的智能台灯控制系统仿真( proteus仿真+程序+原理图+报告+讲解视频)

51单片机的红外光敏检测智能台灯控制系统仿真 1.主要功能&#xff1a;2.仿真3. 程序代码4. 原理图5. 设计报告6. 设计资料内容清单&&下载链接 51单片机的红外光敏检测智能台灯控制系统仿真( proteus仿真程序原理图报告讲解视频&#xff09; 仿真图proteus7.8及以上 程…

服务器时间正确,Java程序时区不对问题解决

服务器执行date命令显示时间正确 执行timedatectl status命令结果如下&#xff1a; 看起来是Time zone没有设置好&#xff0c;但是登录另外一台正常的服务器&#xff0c;执行timedatectl status也是一样的 直接写一个简单的Java程序TestTimeZone.java&#xff1a; import ja…

consul 键值对操作命令

1. 创建或更新—>put [rootlocalhost ~]# consul kv put redis/config/connection 5 Success! Data written to: redis/config/connection[rootlocalhost ~]# consul kv put aaaaaaaaaaaa 5 Success! Data written to: aaaaaaaaaaaa /redis/config会生成两个目录&#xff…

【小吉送书—第二期】阿里后端开发:抽象建模经典案例

文章目录 0.引言1.抽象思维2.软件世界中的抽象2.1 命名抽象2.2 分层抽象2.3 原则抽象 3. 经典抽象案例3.1 方案一&#xff1a;战术抽象&#xff0c;多快好省&#xff0c;跑步前进3.2 方案二&#xff1a;深入分析&#xff0c;透过表象&#xff0c;探寻本质 5. 推荐一本书&#x…

基于奇偶模的跨线桥(crossover)分析

文章目录 1、ADS建模2、奇偶模分析2.1 Port1→Port2传输特性2.1.1奇模分析2.1.2偶模分析 2.2 Port1→Port4传输特性 附&#xff1a;正交混合网络的奇偶模分析1、 Port1→Port21.1奇模分析1.2Port1→Port2偶模分析1.3 奇模传输与偶模传输相位关系![在这里插入图片描述](https://…

鸿蒙开发实例 |搭建环境

2019年8月9日&#xff0c;华为在东莞举行华为开发者大会&#xff0c;正式发布鸿蒙操作系统&#xff1b;2020年9月推出了鸿蒙2.0&#xff0c;全面使能全场景生态&#xff0c;具备跨设备、服务流转、极速直达、可视可说、隐私安全五大能力。在2021年6月2日的华为新品发布会中&…

ChatGPT很好,但别想着用来写留学申请文书!

大家必须承认一件事&#xff0c;大多数申请者和 ChatGPT 相比&#xff0c;ChatGPT 产出的文章质量更高—— ChatGPT语言更精准 ChatGPT文章结构更严谨 ChatGPT行文更流畅 …… 但是为什么仍然不建议大家利用人工智能来撰写申请文书呢&#xff1f; 文书至关重要——比大…

IntelliJ IDEA 配合 Maven 的一些技巧(profiles)

IntelliJ IDEA 配合 Maven 的一些技巧 环境 IntelliJ IDEA 2017.1 Maven 3.3.9 Nexus 3.2.1 ## 学习前提 了解 Maven 配置的基本用法 了解私有仓库&#xff0c;比如 nexus 的一些概念 强烈建议把 Maven 的 settings.xml 文件同时放在&#xff1a;%USER_HOME%/.m2/settin…

IDEA中DEBUG技巧

Debug 介绍 Debug 设置 如上图标注 1 所示&#xff0c;表示设置 Debug 连接方式&#xff0c;默认是 Socket。Shared memory 是 Windows 特有的一个属性&#xff0c;一般在 Windows 系统下建议使用此设置&#xff0c;相对于 Socket 会快点。 ## Debug 常用快捷键 Win 快捷键M…