Arthas,你真是Java程序员的大力丸

您好,我是码农飞哥(wei158556),感谢您阅读本文,欢迎一键三连哦
💪🏻 1. Python基础专栏,基础知识一网打尽,9.9元买不了吃亏,买不了上当。 Python从入门到精通
😁 2. 毕业设计专栏,毕业季咱们不慌忙,几百款毕业设计等你选。
❤️ 3. Python爬虫专栏,系统性的学习爬虫的知识点。9.9元买不了吃亏,买不了上当 。python爬虫入门进阶
❤️ 4. Ceph实战,从原理到实战应有尽有。 Ceph实战
❤️ 5. Java高并发编程入门,打卡学习Java高并发。 Java高并发编程入门

文章目录

    • 1. Arthas是什么
    • 2. Arthas的使用场景
      • 2.1 性能问题定位
      • 2.2 实时调试
      • 2.3 内存分析
      • 2.4 线上问题快速定位
    • 3. Arthas怎么使用
      • 3.1 下载安装
      • 3.2 运行Arthas
      • 3.4 使用Arthas命令
      • **3.5 退出**
    • 4. Arthas的常用操作
      • 4.1. 全局监控
      • 4.2. 定位CPU最高的方法
      • 4.3. 线程死锁
      • 4.4. 代码反编译
      • 4.5. 查看方法信息:
      • 4.6. 查看静态变量:
      • 4.7. 查看方法的调用耗时

1. Arthas是什么

Arthas(阿尔萨斯)是一款由阿里巴巴开源团队开发的Java应用性能监控与诊断工具。它作为一种开源的Java诊断工具,主要用于在生产环境中实时监控、分析和诊断Java应用程序的性能问题。Arthas提供了一系列的命令行工具,可以实时查看Java应用的运行状态、堆栈信息、方法执行耗时等关键性能数据,帮助开发者快速定位并解决问题。

2. Arthas的使用场景

Arthas适用于各种Java应用场景,特别是在生产环境中解决实时性能问题。以下是一些常见的使用场景:

2.1 性能问题定位

Arthas可以实时监控应用程序的性能数据,包括方法执行时间、线程状态等,帮助开发者快速定位潜在的性能瓶颈。

2.2 实时调试

在生产环境中,使用Arthas可以实时进行代码调试,查看变量的值、修改变量的值,甚至动态加载类,而不需要重启应用。

2.3 内存分析

Arthas支持对Java应用的内存进行实时分析,帮助开发者查找内存泄漏、优化内存使用等问题。

2.4 线上问题快速定位

Arthas可以在生产环境中实时诊断问题,无需重启应用,从而快速定位线上故障,提高故障排查效率。

3. Arthas怎么使用

Arthas的使用相对简单,主要通过命令行工具进行操作。以下是一些基本的使用步骤:

3.1 下载安装

首先,通过官方网站或Maven仓库下载Arthas,并解压到本地目录。

官方文档:https://alibaba.github.io/arthas

到官方的开源地址:https://github.com/alibaba/arthas,或者国内的Gitee地址下去下载arthas的jar包。

# github下载
wget https://alibaba.github.io/arthas/arthas-boot.jar
# 或者 Gitee 下载
wget https://arthas.gitee.io/arthas-boot.jar
# 打印帮助信息
java -jar arthas-boot.jar -h

3.2 运行Arthas

Arthas 只是一个 java 程序,所以可以直接用 java -jar 运行。运行时或者运行之后要选择要监测的 Java 进程。

# 运行方式1,先运行,在选择 Java 进程 PID
java -jar arthas-boot.jar
# 选择进程(输入[]内编号(不是PID)回车)
[INFO] arthas-boot version: 3.5.0
[INFO] Found existing java process, please choose one and hit RETURN.
* [1]: 24480 com.Arthas[2]: 20520 com.jay.demos.ArthasTest[3]: 16200 org.jetbrains.jps.cmdline.Launcher[4]: 21032 org.jetbrains.idea.maven.server.RemoteMavenServer# 运行方式2,运行时选择 Java 进程 PID
java -jar arthas-boot.jar [PID]

image-20240103171507894

3.4 使用Arthas命令

一旦连接成功,可以使用各种Arthas命令进行实时监控、诊断,例如:dashboard查看仪表盘、trace追踪方法调用、watch监控变量等。下面列举一些常用命令。

命令介绍
dashboard当前系统的实时数据面板
thread查看当前 JVM 的线程堆栈信息
watch方法执行数据观测
trace方法内部调用路径,并输出方法路径上的每个节点上耗时
stack输出当前方法被调用的调用路径
tt方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
monitor方法执行监控
jvm查看当前 JVM 信息
vmoption查看,更新 JVM 诊断相关的参数
sc查看 JVM 已加载的类信息
sm查看已加载类的方法信息
jad反编译指定已加载类的源码
classloader查看 classloader 的继承树,urls,类加载信息
heapdump类似 jmap 命令的 heap dump 功能

3.5 退出

使用 shutdown 退出时 Arthas 同时自动重置所有增强过的类 。
在这里插入图片描述

4. Arthas的常用操作

上面已经了解了Arthas的使用场景以及启动方式,下面就来说说Arthas的使用方式。

首先,编写一个有各种异常场景的代码。这个代码模拟了CPU过高,线程阻塞,线程死锁,内存不断被消耗等场景。

将代码上传到Linux服务器上,通过 1. javac ArthasTest.java 命令编译将ArthasTest.java文件编译成ArthasTest.class文件。接着通过 java ArthasTest 命令来运行此文件。

import java.util.HashSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** <p>* Arthas Demo* 公众号:码农飞哥** @Author 码农飞哥*/public class ArthasTest {private static HashSet hashSet = new HashSet();/*** 线程池,大小1*/private static ExecutorService executorService = Executors.newFixedThreadPool(1);public static void main(String[] args) {// 模拟 CPU 过高cpu();// 模拟线程阻塞thread();// 模拟线程死锁deadThread();// 不断的向 hashSet 集合增加数据addHashSetThread();}/*** 不断的向 hashSet 集合添加数据*/public static void addHashSetThread() {// 初始化常量new Thread(() -> {int count = 0;while (true) {try {hashSet.add("count" + count);Thread.sleep(10000);count++;} catch (InterruptedException e) {e.printStackTrace();}}}).start();}public static void cpu() {cpuHigh();cpuNormal();}/*** 极度消耗CPU的线程*/private static void cpuHigh() {Thread thread = new Thread(() -> {while (true) {System.out.println("极度消耗CPU的线程,任务死循环,cpu start 100");}});// 添加到线程executorService.submit(thread);}/*** 普通消耗CPU的线程*/private static void cpuNormal() {for (int i = 0; i < 10; i++) {new Thread(() -> {while (true) {System.out.println("普通消耗CPU的线程,任务睡眠3000毫秒,死循环,cpu start");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}}).start();}}/*** 模拟线程阻塞,向已经满了的线程池提交线程*/private static void thread() {Thread thread = new Thread(() -> {while (true) {System.out.println("模拟线程阻塞,thread start");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}});// 添加到线程executorService.submit(thread);}/*** 死锁*/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();}
}

4.1. 全局监控

首先通过 dashboard 命令查看当前系统的实时数据面板。结果如下,我们看到有两个线程的状态是BLOCKED状态。

image-20240103192316398

4.2. 定位CPU最高的方法

上面的代码例子有一个 CPU 空转的死循环,非常的消耗 CPU性能,那么怎么找出来呢?

使用 thread查看所有线程信息,同时会列出每个线程的 CPU 使用率,可以看到图里 ID 为12 的线程 CPU 使用100%。

img

使用命令 thread 12 查看 CPU 消耗较高的 12 号线程信息,可以看到 CPU 使用较高的方法和行数。

img

上面是通过先观察总体的线程信息,然后查看具体的线程运行情况,如果只是为了寻找CPU使用较高的线程,那么可以通过 thread -n[显示的线程个数],就可以排列出 CPU 使用率 Top N 的线程。

img

4.3. 线程死锁

在介绍线程死锁之前,首先回顾一下线程的几种常见状态:

  1. RUNNABLE : 线程正在运行状态
  2. TIMED_WAITIN:线程在等待运行中,调用以下方法会进入TIMED_WAITIN状态
    1. Thread#sleep()
    2. Object#wait() 并加了超时参数
    3. Thread#join() 并加了超时参数
    4. LockSupport#parkNanos()
    5. LockSupport#parkUntil()
  3. WAITIN:线程在等待运行中,调用以下方法会进入WAITIN状态
  4. Thread#sleep()
  5. Object#wait() 并加了超时参数
  6. Thread#join() 并加了超时参数
  7. LockSupport#parkNanos()
  8. LockSupport#parkUntil()
  9. BLOCKED 阻塞,等待锁

上面的模拟代码里,定义了线程池大小为1 的线程池,然后在 cpuHigh 方法里提交了一个线程,在 thread方法再次提交了一个线程,后面的这个线程因为线程池已满,会阻塞下来。

使用 thread | grep pool 命令查看线程池里线程信息。

上面的模拟代码里 deadThread方法实现了一个死锁,使用 thread -b 命令查看直接定位到死锁信息。

	/*** 死锁*/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();}

image-20240103195808453

4.4. 代码反编译

通过 jad ArthasTest 命令可以反编译代码。

image-20240103194444183

4.5. 查看方法信息:

通过sm命令可以查看类中的所有方法信息。

image-20240103194353959

4.6. 查看静态变量:

通过ognl ‘@ArthasTest@hashSet’ 命令可以查看 ArthasTest类的hashSet 静态变量的值。

image-20240103194000623

4.7. 查看方法的调用耗时

先定义一个测试的方法,这里定义了UserController类以及UserServiceImpl类,UserController类作为接口的总入口。

import java.util.HashMap;@RestController
@Slf4j
public class UserController {@Autowiredprivate UserServiceImpl userService;@GetMapping(value = "/user")public HashMap<String, Object> getUser(Integer uid) throws Exception {log.info("------模拟用户查询,uid={}----", uid);// 模拟用户查询userService.get(uid);HashMap<String, Object> hashMap = new HashMap<>();hashMap.put("uid", uid);hashMap.put("name", "name" + uid);return hashMap;}
}

UserServiceImpl类作为业务实现。

package com.jay.demos.web;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;@Service
@Slf4j
public class UserServiceImpl {public void get(Integer uid) throws Exception {check(uid);service(uid);redis(uid);mysql(uid);}public void service(Integer uid) throws Exception {int count = 0;for (int i = 0; i < 10; i++) {count += i;}log.info("service  end {}", count);}public void redis(Integer uid) throws Exception {int count = 0;for (int i = 0; i < 10000; i++) {count += i;}log.info("redis  end {}", count);}public void mysql(Integer uid) throws Exception {long count = 0;for (int i = 0; i < 10000000; i++) {count += i;}log.info("mysql end {}", count);}public boolean check(Integer uid) throws Exception {if (uid == null || uid < 0) {log.error("uid不正确,uid:{}", uid);throw new Exception("uid不正确");}return true;}
}

如果要通过一个接口中,各部分的耗时,则可以使用: trace [类地址] [方法名] 。例如本例中的就是 trace com.jay.demos.web.UserController getUser

image-20240103204500535

image-20240103205037173

image-20240103204943468

参考:

https://cloud.tencent.com/developer/article/1534894

【昵称】码农飞哥
【城市】合肥
【个人介绍】 
1.某厂高级 Java 开发,8 年开发经验
2. 老徐八年合伙人|飞巴三年合伙人|小林三年合伙人|AI 破局会员
3. CSDN 博客专家,全网 15 万粉丝,累计阅读量228万
4. 写技术类商业征文两年GMV六位数
5. 卖毕业设计单月变现 2 万,CSDN付费专栏变现1万
CSDN平台:https://blog.csdn.net/u014534808
#公众号:码农飞哥
【可提供资源】 
1.社群,朋友圈推广 3000+好友(CSDN博主粉丝居多)
2.GPT、Calude、MJ 等大部分 AI 工具的用法、信息和资源。
3.CSDN 涨粉经验,付费专栏编写经验
4.Java 和 Python 软件的开发能力
5.多个长期合作的广告主想与我交流的小伙伴可以可以点击下方二维码加我 WX: wei158556

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

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

相关文章

印章管理详解|契约锁帮助提前预防99%的印章风险

传统实体印章不仅存在私刻私盖、盗用乱用、易伪造等安全隐患&#xff0c;此外&#xff0c;线下面签的方式也不便于异地、非工作时间用印&#xff0c;分公司用印常常两地来回跑。组织的印章到底怎么“管”才能保障安全和使用效率&#xff1f; 一、 印章管理风险有哪些&#xff…

系统概要设计说明书

系统概要设计说明书 1.整体架构 2.功能架构 3.技术架构 4.运行环境设计 5.设计目标 6.接口设计 7.性能设计 8.运行设计 9.出错设计 全文档获取进主页

面试算法107:矩阵中的距离

题目 输入一个由0、1组成的矩阵M&#xff0c;请输出一个大小相同的矩阵D&#xff0c;矩阵D中的每个格子是矩阵M中对应格子离最近的0的距离。水平或竖直方向相邻的两个格子的距离为1。假设矩阵M中至少有一个0。 例如&#xff0c;图&#xff08;a&#xff09;是一个只包含0、1的…

Docker安装Jenkins,配置Maven和Java

前言 这是一个java的springboot项目&#xff0c;使用maven构建 安装准备 需要将maven和jdk安装在服务器上&#xff0c;Jenkins需要用到&#xff0c;还有创建一个jenkins的目录&#xff0c;安装命令如下&#xff1a; docker run -d -uroot -p 9095:8080 -p 50000:50000 --n…

时间序列数据库选型: influxdb; netdiscover列出docker实例们的ip

influxdb influxdb: 有收费版本、有开源版本 docker run -itd --name influxdb-dev -p 8086:8086 influxdb #influxdb的web客户端(端口8003)被去掉了 #8006是web-service端口docker pull chronograf docker run -d -p 8888:8888 --name chronograf-dev chronografsudo netst…

对比fwrite、mmap、DirectIO 的内存、性能开销,剖析 Page Cache

背景 如上图所示&#xff1a;应用程序写文件有三种形式。 fwrite : 应用程序 -> fwrite(Buffered IO) -> File System -> Page Cache -> Block IO Layer -> Device & Disk etc.mmap : 应用程序 -> mmap -> Page Cache -> Block IO Layer -> De…

【LLM】vLLM部署与int8量化

Acceleration & Quantization vLLM vLLM是一个开源的大型语言模型&#xff08;LLM&#xff09;推理和服务库&#xff0c;它通过一个名为PagedAttention的新型注意力算法来解决传统LLM在生产环境中部署时所遇到的高内存消耗和计算成本的挑战。PagedAttention算法能有效管理…

虾皮商品标题:如何创建有效的虾皮商品标题

虾皮&#xff08;Shopee&#xff09;平台是一个非常受欢迎的电商平台&#xff0c;为卖家提供了一个广阔的销售渠道。在虾皮上&#xff0c;一个有效的商品标题是吸引潜在买家注意力的关键元素之一。一个好的商品标题能够吸引更多的点击和浏览量&#xff0c;从而提高销售机会。下…

什么是API网关代理?

带有API网关的代理服务显着增强了用户体验和性能。特别是对于那些使用需要频繁创建和轮换代理的工具的人来说&#xff0c;使用 API 可以节省大量时间并提高效率。 了解API API&#xff08;即应用程序编程接口&#xff09;充当服务提供商和用户之间的连接网关。通过 API 连接&a…

【PostgreSQL】在DBeaver中实现序列、函数、视图、触发器设计

【PostgreSQL】在DBeaver中实现序列、函数、触发器、视图设计 基本配置一、序列1.1、序列使用1.1.1、设置字段为主键&#xff0c;数据类型默认整型1.1.2、自定义序列&#xff0c;数据类型自定义 1.2、序列延申1.2.1、理论1.2.2、测试1.2.3、小结 二、函数2.1、SQL直接创建2.1.1…

Python教程37:使用turtle画一个戴帽子的皮卡丘

---------------turtle源码集合--------------- Python教程36&#xff1a;海龟画图turtle写春联 Python源码35&#xff1a;海龟画图turtle画中国结 Python源码31&#xff1a;海龟画图turtle画七道彩虹 Python源码30&#xff1a;海龟画图turtle画紫色的小熊 Python源码29&a…

基于宝塔搭建Discuz!论坛

一、安装宝塔 我是在我的虚拟机上安装图的宝塔 虚拟机版本&#xff1a;Ubuntu 18.04 wget -O install.sh https://download.bt.cn/install/install-ubuntu_6.0.sh && sudo bash install.sh 6dca892c安装完成之后在浏览器输入你的地址 https://你的域名&#xff08;或…

基于JavaWeb+BS架构+SpringBoot+Vue校园一卡通系统的设计和实现

基于JavaWebBS架构SpringBootVue校园一卡通系统的设计和实现 文末获取源码Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 文末获取源码 Lun文目录 第一章 概述 4 1.1 研究背景 4 1.2研究目的及意义 4 1.3国内外发展现状 4 1…

网络安全之你的浏览器记录真的安全吗?

密码是每个人最私密的东西&#xff0c;轻易是不会展示给他人的&#xff0c;那么我如何能知道你电脑上浏览器里保存的密码呢&#xff1f;浏览器是大家在网上冲浪最常用的软件&#xff0c;在登录一些网站填写账号密码后&#xff0c;浏览器为了方便大家使用&#xff0c;会提示是否…

unity小程序websocket:nginx配置https (wss)转http (ws)及其他问题解决

目录 前言 实际运用场景 处理流程如下 nginx配置ssl和wss 配置过程中遇到的问题 1、无法连接服务器 2、通过IP可以访问&#xff0c;域名却不行 问题描述 解决 3、如何判断该域名是否备案了 前言 为了服务器网络的通用性&#xff0c;我们在实现移动端的游戏转微信小程序…

Python教程38:使用turtle画动态粒子爱心+文字爱心

Turtle库是Python语言中的一个标准库&#xff0c;它提供了一种有趣的方式来介绍编程和图形绘制的基本概念。Turtle库使用一个虚拟的“海龟”来绘制图形。你可以控制海龟的方向、速度和位置&#xff0c;通过向前移动、向左转或向右转等命令来绘制线条、圆弧多边形等图形。 -----…

Java 反射(一)

反射 1.反射的介绍 1.反射机制允话程序在执行期间借助于Refelction API取得任何类的信息&#xff08;比如成员变量&#xff0c;构造器&#xff0c;成员方法等&#xff09;并能操作对象的属性及方法&#xff0c;反射在设计模式和框架底层都会用到 2.加载完类之后&#xff0c;在…

API调试怎么做?Apipost快速上手

前言 Apipost是一款支持 RESTful API、SOAP API、GraphQL API等多种API类型&#xff0c;支持 HTTPS、WebSocket、gRPC多种通信协议的API调试工具。除此之外&#xff0c;Apipost 还提供了自动化测试、团队协作、等多种功能。这些丰富的功能简化了工作流程&#xff0c;提高了研发…

CodeWave智能开发平台--03--目标:应用创建--08联系人管理

摘要 本文是网易数帆CodeWave智能开发平台系列的第11篇&#xff0c;主要介绍了基于CodeWave平台文档的新手入门进行学习&#xff0c;实现一个完整的应用&#xff0c;本文主要完成08联系人管理 CodeWave智能开发平台的11次接触 CodeWave参考资源 网易数帆CodeWave开发者社区…

【VRTK】【Unity】【VR开发】Linear Drives

课程配套学习项目源码资源下载 https://download.csdn.net/download/weixin_41697242/88485426?spm=1001.2014.3001.5503 【概述】 前面一篇讨论了角度运动机制,本篇讨论线性运动机制。和角度运动机制类似,线性运动机制提供了更为仿真的互动机制。也分为基于物理的和不基于…