千家信息网

Arthas如何实现CPU 排查与代码热更新

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本篇文章给大家分享的是有关Arthas如何实现CPU 排查与代码热更新,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1.前言背景线上代码
千家信息网最后更新 2026年11月01日Arthas如何实现CPU 排查与代码热更新

本篇文章给大家分享的是有关Arthas如何实现CPU 排查与代码热更新,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

1.前言

背景

线上代码经常会出现 CPU 占用过高的情况,按以往经验我会使用 top 指令,进一步借助于 jstack 去查看具体信息从而进行问题排查,但基本上都逃不过需要重新发包的局面,及时是一个增量包,应用也需要短暂停启。后来运维大兄弟让我试一下 Arthas,说是可以进行代码的热更新操作,正好来试一下。

环境

JDK1.8
SPringBoot 2.2.2
Arthas
Linux

测试代码:

@RequestMapping(value = "/bigThread")@ResponseBodypublic String bigThread(int id) {    ArthasService.test();while (true) {        Thread t2 = new Thread();        t2.start();        id ++;if(100000 == id) {return String.valueOf(id);        }    }}

思路

2.thread -b 查看是否有阻塞线程

thread -b, 找出当前阻塞其他线程的线程,执行完之后并未发现,说明该线程并非一直阻塞、一直执行的。

4.thread id 查看具体信息

在上一步基础上,我们进一步查看,thread 15(因为上面的 ID=15)。

4.png

他的大致意思就是:线程在等待一个条件从而继续执行,可以看到方法是在执行 LinkedBlockingQueue.take 方法时候,查看这个方法的 API 提示如下:

public E take() throws InterruptedException {    E x;int c = -1;final AtomicInteger count = this.count;final ReentrantLock takeLock = this.takeLock;    takeLock.lockInterruptibly();try {while (count.get() == 0) {            notEmpty.await();        }        x = dequeue();        c = count.getAndDecrement();if (c > 1)            notEmpty.signal();    } finally {        takeLock.unlock();    }if (c == capacity)        signalNotFull();return x;}

其中:AtomicInteger 是保证高并发情况下的原子性,ReentrantLock 标识可重入锁,都是 JUC 包下需要了解的这里不赘述,需要的百度了解下。

这段代码关键点就在于:notEmpty.await(),从队列中消费数据,当队列为空是,线程阻塞,所以我们大致知道现在出现的问题是线程阻塞,但是还是不知道具体哪行代码的问题。

如果能够明确知道这次更改了哪些代码,可以直接执行步骤 6,不知道的话可以通过步骤 5 来定位问题。

5.watch 查看哪个 Controller 执行了代码

watch org.springframework.web.servlet.DispatcherServlet getHandler returnObj

这个脚本可以检测一切通过 DispatcherServlet 匹配 Handler 的方法,也就是进入 Controller 的请求,如下:

找到了对应的代码之后,我们来进一步观察异常信息,这里可能会有一个问题:就是我明明能通过日志去查看错误信息,为什么还需要这么繁琐的去操作。我的业务场景是:日志还是非常大的,刚捞到就被刷过去了,这时候定位日志不是很好操作,当然想捞下来日志肯定也是可以的,也很直观,我一般也都是去查看日志进行问题定位,这里也是提供一个思路。

6.watch 该方法异常信息

watch 类全路径 方法名 "{params[0],throwExp}" -e -x 2

6.png

如上,错误很直观的提示了出来,下面就可以修复解决了,这里我们也可以通过 trace 指令,查看执行时长:

trace 类全路径 方法名 "{params[0],throwExp}" -e -x 2

返回信息如下,也可以看到错误信息,和每个方法执行的时长。

[arthas@10999]$ trace com.arthas.controller.OrderController bigThreadPress Q or Ctrl+C to abort.Affect(class count: 1 , method count: 1) cost in 53 ms, listenerId: 10`---ts=2020-08-19 14:45:57;thread_name=http-nio-0.0.0.0-8080-exec-10;id=16;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1f1c7bf6    `---[1452.684406ms] com.arthas.controller.OrderController:bigThread() [throws Exception]        +---[0.168814ms] com.arthas.service.ArthasService:test() #20`---throw:java.lang.OutOfMemoryError #-2 [unable to create new native thread]

7.jad 反编译热更新

在上面知道问题之后,我们就来定位问题就好了。

命令:jad 类全路径 方法名

[arthas@13190]$ jad com.arthas.controller.OrderControllerClassLoader:                                                                                                                                                                                +-org.springframework.boot.loader.LaunchedURLClassLoader@17f052a3                                                                                                                             +-sun.misc.Launcher$AppClassLoader@3d4eac69                                                                                                                                                   +-sun.misc.Launcher$ExtClassLoader@45f45fa1                                                                                                                                             Location:                                                                                                                                                                                   file:/opt/software/arthas/Arthas.jar!/BOOT-INF/classes!/                                                                                                                                    /* * Decompiled with CFR. *  * Could not load the following classes: *  com.arthas.service.ArthasService *  org.springframework.stereotype.Controller *  org.springframework.web.bind.annotation.RequestMapping *  org.springframework.web.bind.annotation.ResponseBody */package com.arthas.controller;import com.arthas.service.ArthasService;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;@Controllerpublic class OrderController {@RequestMapping(value={"/bigThread"})@ResponseBodypublic String bigThread(int id) {        ArthasService.test();do {            Thread t2 = new Thread();            t2.start();        } while (100000 != ++id);return String.valueOf(id);    }}Affect(row-cnt:1) cost in 1513 ms.

此时代码就被反编译了,为了能够更改,所以我们需要输出为 java 文件。

指令:jad com.arthas.controller.OrderController > /tmp/OrderController.java

即:jad 类全路径 方法名 > 存储路径/存储名称

然后到 tmp 路径下 vi 修改 java 文件即可,修改完成之后,查看对应的 classloader 为编译做准备。

sc -d *OrderController | grep classLoaderHashmc -c 17f052a3 /tmp/OrderController.java -d /tmp

但是这里编译出错了,官方提示:

编译前调用

[arthas@13190]$ trace com.arthas.controller.OrderController bigThreadPress Q or Ctrl+C to abort.Affect(class count: 1 , method count: 1) cost in 77 ms, listenerId: 2`---ts=2020-08-19 15:51:46;thread_name=http-nio-0.0.0.0-8080-exec-1;id=d;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1f1c7bf6    `---[6734.666529ms] com.arthas.controller.OrderController:bigThread() [throws Exception]        +---[0.786517ms] com.arthas.service.ArthasService:test() #20`---throw:java.lang.OutOfMemoryError #-2 [unable to create new native thread]

更新前代码

@RequestMapping(value = "/bigThread")@ResponseBodypublic String bigThread(int id) {    ArthasService.test();while (true) {        Thread t2 = new Thread();        t2.start();        id ++;if(100000 == id) {return String.valueOf(id);        }    }}

更新后代码

@RequestMapping(value = "/bigThread")@ResponseBodypublic String bigThread(int id) {    ArthasService.test();    Thread t2 = new Thread();    t2.start();return "success";}

编译指令

[arthas@13190]$ redefine /tmp/OrderController.classredefine success, size: 1, classes:com.arthas.controller.OrderController

编译后调用三次

`---ts=2020-08-19 15:52:02;thread_name=http-nio-0.0.0.0-8080-exec-3;id=f;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1f1c7bf6    `---[5.609405ms] com.arthas.controller.OrderController:bigThread()        `---[0.204675ms] com.arthas.service.ArthasService:test() #20`---ts=2020-08-19 15:52:04;thread_name=http-nio-0.0.0.0-8080-exec-4;id=10;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1f1c7bf6    `---[3.900149ms] com.arthas.controller.OrderController:bigThread()        `---[0.14636ms] com.arthas.service.ArthasService:test() #20`---ts=2020-08-19 15:52:04;thread_name=http-nio-0.0.0.0-8080-exec-5;id=11;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1f1c7bf6    `---[1.90945ms] com.arthas.controller.OrderController:bigThread()        `---[0.147353ms] com.arthas.service.ArthasService:test() #20

可以发现时间从 6734.666529ms 变成 3ms 左右,说明热更新的代码生效了。

以上就是Arthas如何实现CPU 排查与代码热更新,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。

代码 方法 问题 更新 信息 线程 编译 路径 日志 阻塞 指令 定位 就是 错误 进一 提示 直观 可以通过 思路 情况 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 西安纸贵互联网科技有限公司 互联网和科技技术 互联网中国科技 深圳互联网科技公司 万易互联网科技有限公司 互联网金融和金融科技 四个字互联网科技公司取名 太原新华互联网科技学校怎么样 广州优美互联网科技 互联网科技商业 民营互联网公司国防科技 天津腾达互联网科技有限公司 允成互联网科技有限公司融资 乌鲁木齐新华智原互联网科技学校 朱啸虎曾投资哪些互联网科技企业 区块链结合互联网科技 互联网营销推广黑科技 中国新注册互联网科技 第三届互联网大会安防黑科技 黑龙江互联网科技公司 科技服务与互联网 嘟嘟瓜互联网科技 丰台科技园 互联网 恒银科技与互联网金融 创业天下互联网科技有限公司 互联网系的金融科技公司 深圳育鹏互联网科技有限公司招聘 科技互联网的核心竞争力 互联网硬科技公司 好易买互联网科技
0