- Arthas是阿里的一款开源的线上JVM运维工具。开源地址:Github-alibaba/arthas ,最近由于线上问题频繁,但面对庞大的用户量,我们无法做出及时的重启,为此入手Arthas,旨在快速定位线上问题,解决用户困扰
安装
快速安装
-
使用
arthas-boot
(推荐)下载
arthas-boot.jar
,然后用java -jar
的方式启动:wget https://alibaba.github.io/arthas/arthas-boot.jar java -jar arthas-boot.jar
-
如果下载速度比较慢,可以使用aliyun的镜像:
java -jar arthas-boot.jar --repo-mirror aliyun --use-http
-
如果从github下载有问题,可以使用gitee镜像
wget https://arthas.gitee.io/arthas-boot.jar
使用as.sh
安装
-
Arthas 支持在 Linux/Unix/Mac 等平台上一键安装
curl -L https://alibaba.github.io/arthas/install.sh | sh
对于
as.sh
方式,在安装的过程中还需要走互联网,为此对应博主这种企业内网无法联通外部网络的环境下,该方式并不通用上述命令会下载启动脚本文件
as.sh
到当前目录,你可以放在任何地方或将其加入到$PATH
中。-
直接在shell下面执行
./as.sh
,就会进入交互界面。也可以执行./as.sh -h
来获取更多参数信息。- 使用
as.sh
脚本执行的时候,需要先安装telnet
,否则会报错
- 使用
-
如果从github下载有问题,可以使用gitee镜像
curl -L https://arthas.gitee.io/install.sh | sh
全量安装
点击下载
-
下载完成后
arthas-packaging-3.1.1-bin
解压后,在文件夹里有arthas-boot.jar
,直接用java -jar
的方式启动:java -jar arthas-boot.jar
-
打印帮助信息:
java -jar arthas-boot.jar -h
卸载
-
在 Linux/Unix/Mac 平台
rm -rf ~/.arthas/ rm -rf ~/logs/arthas
Windows平台直接删除user home下面的
.arthas
和logs/arthas
目录
启动
java -jar arthas-boot.jar --target-ip 0.0.0.0
默认情况下, arthas server 侦听的是
127.0.0.1
这个IP,如果希望远程可以访问,可以使用--target-ip
的参数-
arthas-boot
是Arthas
的启动程序,它启动后,会列出所有的 Java 进程,输入需要诊断的目标进程序号即可
-
Arthas支持通过 Web Socket来连接。
- 当在本地启动时,可以访问
http://127.0.0.1:8563/
,通过浏览器来使用 Arthas。 - 输入
help
可以看到常用的帮助命令:
- 当在本地启动时,可以访问
-
arthas-boot.jar
支持很多参数,可以执行java -jar arthas-boot.jar -h
查看D:\arthas>java -jar arthas-boot.jar -h [INFO] arthas-boot version: 3.1.1 Usage: arthas-boot [-v] [--session-timeout
] [--arthas-home ] [--use-version ] [--target-ip ] [--attach-only] [--height ] [--width ] [-c ] [--repo-mirror ] [--versions] [-f ] [--telnet-port ] [--use-http] [-h] [--http-port ] [pid] Bootstrap Arthas EXAMPLES: java -jar arthas-boot.jar java -jar arthas-boot.jar --target-ip 0.0.0.0 java -jar arthas-boot.jar --telnet-port 9999 --http-port -1 java -jar arthas-boot.jar -c 'sysprop; thread' java -jar arthas-boot.jar -f batch.as java -jar arthas-boot.jar --use-version 3.1.1 java -jar arthas-boot.jar --versions java -jar arthas-boot.jar --session-timeout 3600 java -jar arthas-boot.jar --attach-only java -jar arthas-boot.jar --repo-mirror aliyun --use-http WIKI: https://alibaba.github.io/arthas Options and Arguments: -v,--verbose Verbose, print debug info. --session-timeout The session timeout seconds, default 1800 (30min) --arthas-home The arthas home --use-version Use special version arthas --target-ip The target jvm listen ip, default 127.0.0.1 --attach-only Attach target process only, do not connect --height arthas-client terminal height --width arthas-client terminal width -c,--command Command to execute, multiple commands separated by ; --repo-mirror Use special maven repository mirror, value is center/aliyun or http repo url. --versions List local and remote arthas versions -f,--batch-file The batch file to execute --telnet-port The target jvm listen telnet port, default 3658 --use-http Enforce use http to download, default use https -h,--help Print usage --http-port The target jvm listen http port, default 8563 Target pid
使用技巧
- 每个命令,都可以加上
-h
来查看对应的帮助信息,例如:sc -h
-
Tab
自动补全,例如:sysprop java.
按下Tab
键,会补全对应的key
- 支持常见的命令行快捷键,比如
ctrl+a/e
,更多输入keymap
查看 - 历史命令补全,输入一半时,按下
Up/↑
或Down/↓
来匹配,例如sysprop ja
之后,按下↑
会帮你自动补全 - 管道命令支持,例如
sysprop | wc -l
退出
-
exit
或quit
可以退出 Arthas- 退出 Arthas 之后,还可以再次使用
java -jar arthas-boot.jar
来链接 -
exit/quit
命令只是退出当前 session,arthas server
还在目标进程中运行,shutdown
命令才能完全退出 Arthas
- 退出 Arthas 之后,还可以再次使用
常用命令
dashboard
dashboard
命令可以查看系统的实时数据面板。-
q
或ctrl+c
可以退出数据面展示
数据说明:
- ID: Java级别的线程ID,注意这个ID不能跟jstack中的nativeID一一对应
- NAME: 线程名
- GROUP: 线程组名
- PRIORITY: 线程优先级, 1~10之间的数字,越大表示优先级越高
- STATE: 线程的状态
- CPU%: 线程消耗的cpu占比,采样100ms,将所有线程在这100ms内的cpu使用量求和,再算出每个线程的cpu使用占比。
- TIME: 线程运行总时间,数据格式为分:秒
- INTERRUPTED: 线程当前的中断位状态
- DAEMON: 是否是daemon线程
thread
查看当前线程信息,查看线程的堆栈
-
参数说明
参数名称 参数说明 id 线程id [n:] 指定最忙的前N个线程并打印堆栈 [b] 找出当前阻塞其他线程的线程 [i
]指定cpu占比统计的采样间隔,单位为毫秒 thread 1
打印线程 ID 1 的线程栈信息
-
查看 CPU 使用率 top n 的线程的栈,当前最忙的前 n 个线程:
thread -n 3
-
查看 5 秒内的 CPU 使用率 top n 的线程栈:
thread -n 3 -i 5000
* 在该命令中,arthas 会停顿5秒,进行计算得出结果,为阿里点赞
-
查看线程是否有阻塞:
thread -b
- 有时候我们发现应用出现卡顿,未响应, 通常是由于某个线程占用着某个锁, 并且其他线程都在等待这把锁的释放。 为了排查这类问题,此时使用
-b
参数,可以找到问题所在。- 目前只支持找出synchronized关键字阻塞住的线程, 如果是
java.util.concurrent.Lock
, 目前还不支持
- 目前只支持找出synchronized关键字阻塞住的线程, 如果是
- 有时候我们发现应用出现卡顿,未响应, 通常是由于某个线程占用着某个锁, 并且其他线程都在等待这把锁的释放。 为了排查这类问题,此时使用
jvm
-
查看当前JVM信息
$ jvm RUNTIME ----------------------------------------------------------------------------------------------------------------------- MACHINE-NAME 18280@DESKTOP-040TJ8N JVM-START-TIME 2019-07-21 22:52:26 MANAGEMENT-SPEC-VERSION 1.2 SPEC-NAME Java Virtual Machine Specification SPEC-VENDOR Oracle Corporation SPEC-VERSION 1.8 VM-NAME Java HotSpot(TM) 64-Bit Server VM VM-VENDOR Oracle Corporation VM-VERSION 25.131-b11 INPUT-ARGUMENTS -Djava.util.logging.config.file=H:\Development\ide\ideacfg\system\tomcat\Unnamed_pl atform\conf\logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:2139,suspend=y,server=n -javaagent:H:\Development\ide\ideacfg\system\captureAgent\debugger-agent.jar=file:/ C:/Users/guosucong/AppData/Local/Temp/capture5938.props -Dcom.sun.management.jmxremote= -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=127.0.0.1 -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=D:\Development\Tomcat\apache-tomcat-7.0.75\endorsed -Dcatalina.base=H:\Development\ide\ideacfg\system\tomcat\Unnamed_platform -Dcatalina.home=D:\Development\Tomcat\apache-tomcat-7.0.75 -Djava.io.tmpdir=D:\Development\Tomcat\apache-tomcat-7.0.75\temp CLASS-PATH D:\Development\Tomcat\apache-tomcat-7.0.75\bin\bootstrap.jar;D:\Development\Tomcat\ apache-tomcat-7.0.75\bin\tomcat-juli.jar;H:\Development\ide\ideacfg\system\captureA gent\debugger-agent.jar BOOT-CLASS-PATH D:\Development\Java\jdk1.8.0_131\jre\lib\resources.jar;D:\Development\Java\jdk1.8.0 _131\jre\lib\rt.jar;D:\Development\Java\jdk1.8.0_131\jre\lib\sunrsasign.jar;D:\Deve lopment\Java\jdk1.8.0_131\jre\lib\jsse.jar;D:\Development\Java\jdk1.8.0_131\jre\lib \jce.jar;D:\Development\Java\jdk1.8.0_131\jre\lib\charsets.jar;D:\Development\Java\ jdk1.8.0_131\jre\lib\jfr.jar;D:\Development\Java\jdk1.8.0_131\jre\classes;H:\Develo pment\ide\ideacfg\system\captureAgent\debugger-agent-storage.jar LIBRARY-PATH D:\Development\Java\jdk1.8.0_131\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C: \Windows;C:\ProgramData\Oracle\Java\javapath;%APPCAN_PATH%;D:\Development\Oracle\DB \product\11.2.0\dbhome_1\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbe m;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\NVIDIA Corpora tion\PhysX\Common;D:\VisualSVN Server\bin;D:\TortoiseSVN\bin;C:\ProgramData\chocola tey\bin;H:\Android\sdk\tools;H:\Android\sdk\platform-tools;D:\Development\TortoiseG it\bin;D:\Development\nodejs\;D:\Microsoft VS Code\bin;D:\Development\Java\jdk1.8.0 _131\bin;D:\Development\Tomcat\apache-tomcat-7.0.75\bin;D:\Development\apache-maven -3.2.5\bin;D:\auto-tsschecker_v2.1;D:\Development\MySQL\Mysql5_7\MySQLServer\bin;D: \Development\apache-cxf-2.4.2\bin;C:\Users\guosucong\AppData\Local\Microsoft\Window sApps;D:\Development\kotlinc\bin;D:\Development\spring-2.0.0.BUILD-SNAPSHOT\bin;D:\ Development\redis;D:\Development\gradle-4.4.1\bin;H:\Android\sdk\platform-tools;H:\ Android\sdk\tools;D:\Microsoft VS Code\bin;D:\Development\apache-ant-1.9.9\bin;D:\D evelopment\sonarqube-6.7.4\bin;C:\Users\guosucong\AppData\Roaming\npm;D:\Developmen t\Git\bin;D:\Development\flutter\bin;. ----------------------------------------------------------------------------------------------------------------------- CLASS-LOADING ----------------------------------------------------------------------------------------------------------------------- LOADED-CLASS-COUNT 10418 TOTAL-LOADED-CLASS-COUNT 10418 UNLOADED-CLASS-COUNT 0 IS-VERBOSE false ----------------------------------------------------------------------------------------------------------------------- COMPILATION ----------------------------------------------------------------------------------------------------------------------- NAME HotSpot 64-Bit Tiered Compilers TOTAL-COMPILE-TIME 46848(ms) ----------------------------------------------------------------------------------------------------------------------- GARBAGE-COLLECTORS ----------------------------------------------------------------------------------------------------------------------- PS Scavenge 13/216(ms) [count/time] PS MarkSweep 3/291(ms) [count/time] ----------------------------------------------------------------------------------------------------------------------- MEMORY-MANAGERS ----------------------------------------------------------------------------------------------------------------------- CodeCacheManager Code Cache Metaspace Manager Metaspace Compressed Class Space PS Scavenge PS Eden Space PS Survivor Space PS MarkSweep PS Eden Space PS Survivor Space PS Old Gen ----------------------------------------------------------------------------------------------------------------------- MEMORY ----------------------------------------------------------------------------------------------------------------------- HEAP-MEMORY-USAGE 1436024832(1.34 GiB)/268435456(256.00 MiB)/3791650816(3.53 GiB)/1040965944(992.74 M [committed/init/max/used] iB) NO-HEAP-MEMORY-USAGE 113754112(108.48 MiB)/2555904(2.44 MiB)/-1(-1 B)/111507424(106.34 MiB) [committed/init/max/used] PENDING-FINALIZE-COUNT 0 ----------------------------------------------------------------------------------------------------------------------- OPERATING-SYSTEM ----------------------------------------------------------------------------------------------------------------------- OS Windows 10 ARCH amd64 PROCESSORS-COUNT 8 LOAD-AVERAGE -1.0 VERSION 10.0 ----------------------------------------------------------------------------------------------------------------------- THREAD ----------------------------------------------------------------------------------------------------------------------- COUNT 52 DAEMON-COUNT 23 PEAK-COUNT 53 STARTED-COUNT 71 DEADLOCK-COUNT 0 ----------------------------------------------------------------------------------------------------------------------- FILE-DESCRIPTOR ----------------------------------------------------------------------------------------------------------------------- MAX-FILE-DESCRIPTOR-COUNT -1 OPEN-FILE-DESCRIPTOR-COUNT -1 Affect(row-cnt:0) cost in 4 ms.
-
THREAD相关
- COUNT: JVM当前活跃的线程数
- DAEMON-COUNT: JVM当前活跃的守护线程数
- PEAK-COUNT: 从JVM启动开始曾经活着的最大线程数
- STARTED-COUNT: 从JVM启动开始总共启动过的线程次数
- DEADLOCK-COUNT: JVM当前死锁的线程数
-
文件描述符相关
- MAX-FILE-DESCRIPTOR-COUNT:JVM进程最大可以打开的文件描述符数
- OPEN-FILE-DESCRIPTOR-COUNT:JVM当前打开的文件描述符数
sc
- 查找 JVM 加载类,
Search-Class
的简写,这个命令能搜索出所有已经加载到 JVM 中的 Class 信息,sc -d *MathGame
- 如果搜索的是接口,还会搜索所有的实现类。比如查看所有的
Filter
实现类:
sc javax.servlet.Filter
-d
参数可以打印出类加载的具体信息,方便定位类加载问题
sc
支持通配符,比如搜索所有的 StringUtils
:
Copysc *StringUtils
[图片上传失败...(image-2b1ed8-1590935866588)]
打印类的 Field
信息:
Copysc -d -f demo.MathGame
sm
- 查看已加载类的方法信息
Search-Method
的简写,这个命令能搜索出所有已经加载了 Class 信息的方法信息。 - sm 命令只能看到由当前类所声明 (declaring) 的方法,父类则无法看到
- 查看 String 类的全部方法:
sm java.lang.String
- 查看具体方法的信息:
sm java.lang.String toString
- 通过
-d
参数可以打印函数的具体属性,展示每个方法的详细信息
sm -d java.math.RoundingMode
jad
- 反编译指定已加载类的源码 ,
jad
命令将 JVM 中实际运行的 class 的 byte code 反编译成 java 代码,便于你理解业务逻辑 - 参数说明
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
[c:] |
类所属 ClassLoader 的 hashcode |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
- 通过
jad
命令反编译代码:
jad demo.MatthGame
$ jad com.platform.controller.SysConfigController
ClassLoader:
+-WebappClassLoader
context: /platform
delegate: false
repositories:
/WEB-INF/classes/
----------> Parent Classloader:
java.net.URLClassLoader@2d127a61
+-java.net.URLClassLoader@2d127a61
+-sun.misc.Launcher$AppClassLoader@18b4aac2
+-sun.misc.Launcher$ExtClassLoader@6dde5c8c
Location:
/H:/Development/ideaworkspace/platform/platform-framework/target/platform-framework/WEB-INF/classes/
/*
* Decompiled with CFR 0_132.
*
* Could not load the following classes:
* com.platform.annotation.SysLog
* com.platform.controller.AbstractController
* com.platform.entity.SysConfigEntity
* com.platform.service.SysConfigService
* com.platform.utils.PageUtils
* com.platform.utils.Query
* com.platform.utils.R
* com.platform.validator.ValidatorUtils
* org.apache.shiro.authz.annotation.RequiresPermissions
* org.springframework.beans.factory.annotation.Autowired
* org.springframework.web.bind.annotation.PathVariable
* org.springframework.web.bind.annotation.RequestBody
* org.springframework.web.bind.annotation.RequestMapping
* org.springframework.web.bind.annotation.RequestParam
* org.springframework.web.bind.annotation.RestController
*/
package com.platform.controller;
import com.platform.annotation.SysLog;
import com.platform.controller.AbstractController;
import com.platform.entity.SysConfigEntity;
import com.platform.service.SysConfigService;
import com.platform.utils.PageUtils;
import com.platform.utils.Query;
import com.platform.utils.R;
import com.platform.validator.ValidatorUtils;
import java.util.List;
import java.util.Map;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value={"/sys/config"})
public class SysConfigController
extends AbstractController {
@Autowired
private SysConfigService sysConfigService;
@RequestMapping(value={"/list"})
@RequiresPermissions(value={"sys:config:list"})
public R list(@RequestParam Map params) {
Query query = new Query(params);
List configList = this.sysConfigService.queryList((Map)query);
int total = this.sysConfigService.queryTotal((Map)query);
PageUtils pageUtil = new PageUtils(configList, total, query.getLimit(), query.getPage());
return R.ok().put("page", (Object)pageUtil);
}
@RequestMapping(value={"/info/{id}"})
@RequiresPermissions(value={"sys:config:info"})
public R info(@PathVariable(value="id") Long id) {
SysConfigEntity config = this.sysConfigService.queryObject(id);
return R.ok().put("config", (Object)config);
}
@SysLog(value="\u4fdd\u5b58\u914d\u7f6e")
@RequestMapping(value={"/save"})
@RequiresPermissions(value={"sys:config:save"})
public R save(@RequestBody SysConfigEntity config) {
ValidatorUtils.validateEntity((Object)config, (Class[])new Class[0]);
this.sysConfigService.save(config);
return R.ok();
}
@SysLog(value="\u4fee\u6539\u914d\u7f6e")
@RequestMapping(value={"/update"})
@RequiresPermissions(value={"sys:config:update"})
public R update(@RequestBody SysConfigEntity config) {
ValidatorUtils.validateEntity((Object)config, (Class[])new Class[0]);
this.sysConfigService.update(config);
return R.ok();
}
@SysLog(value="\u5220\u9664\u914d\u7f6e")
@RequestMapping(value={"/delete"})
@RequiresPermissions(value={"sys:config:delete"})
public R delete(@RequestBody Long[] ids) {
this.sysConfigService.deleteBatch(ids);
return R.ok();
}
}
- 通过该工具,我们往往能看到线上当前代码的情况,有时候在线上环境中手头没有源代码的情况之下,可以通过该命令对指定的类进行反编译,找到问题的根源,从而快速的定位问题与获取解决方案,该命令可以与其他命令结合,反编译后得出源文件,对文件代码进行修改后通过
mc
命令编译,通过redefine
热加载回JVM内存,达到无需重启,修复线上问题,但是对于反编译出来的源代码,可能出现错乱问题,所以还是慎重使用,一般用于查看线上问题。
mc
redefine
monitor
trace
watch
watch
命令可以查看函数的:
- 参数
- 返回值
- 异常信息
Copywatch demo.MathGame primeFactors returnObj
[图片上传失败...(image-c6fd81-1590935866588)]
Copywatch com.example.demo.arthas.user.UserController * '{params, throwExp}' -x 2
- 第一个参数是类名,支持通配
- 第二个参数是函数名,支持通配
- 第三个参数是定义返回值
-
-x 2
是为了将结果展开
返回值表达式实际是一个 ognl
表示,支持一些内置对象:
- loader
- clazz
- method
- target
- params
- returnObj
- throwExp
- isBefore
- isThrow
- isReturn
watch命令支持按请求耗时进行过滤:
watch com.example.demo.arthas.user.UserController * '{params, returnObj}' '#cost>200'
Arthas在 watch/trace 等命令时,实际上是修改了应用的字节码,插入增强的代码。显式执行 reset 命令,可以清除掉这些增强代码
ognl
获取静态类的静态字段:
ognl '@demo.MathGame@random'
具体,查看执行ognl表达式
trace
方法内部调用路径,并输出方法路径上的每个节点上耗时
trace 命令能主动搜索 class-pattern/method-pattern
对应的方法调用路径,渲染和统计整个调用链路上的所有性能开销和追踪调用链路
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 方法名表达式匹配 |
condition-express | 条件表达式 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[n:] | 命令执行次数 |
#cost | 方法执行耗时 |
很多时候我们只想看到某个方法的 rt 大于某个时间之后的 trace 结果,现在 Arthas 可以按照方法执行的耗时来进行过滤了,例如 trace *StringUtils isBlank '#cost>100'
表示当执行时间超过 100ms 的时候,才会输出 trace 的结果。
watch/stack/trace
这个三个命令都支持 #cost
trace 函数:
$ trace demo.MathGame run
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 42 ms.
`---ts=2018-12-04 00:44:17;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
`---[10.611029ms] demo.MathGame:run()
+---[0.05638ms] java.util.Random:nextInt()
+---[10.036885ms] demo.MathGame:primeFactors()
`---[0.170316ms] demo.MathGame:print()
过滤掉 jdk 的函数:
$ trace -j demo.MathGame run
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 31 ms.
`---ts=2018-12-04 01:09:14;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
`---[5.190646ms] demo.MathGame:run()
+---[4.465779ms] demo.MathGame:primeFactors()
`---[0.375324ms] demo.MathGame:print()
-
-j
: jdkMethodSkip, skip jdk method trace
trace 在执行的过程中本身是会有一定的性能开销,在统计的报告中并未像 JProfiler 一样预先减去其自身的统计开销
stack
输出当前方法被调用的调用路径
很多时候我们都知道一个方法被执行,但这个方法被执行的路径非常多,或者你根本就不知道这个方法是从那里被执行了,此时你需要的是 stack 命令。
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 方法名表达式匹配 |
condition-express | 条件表达式 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[n:] | 执行次数限制 |
据执行时间来过滤:
$ stack demo.MathGame primeFactors '#cost>5'
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 35 ms.
ts=2018-12-04 01:35:58;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
@demo.MathGame.run()
at demo.MathGame.main(MathGame.java:16)
实战
启动 Spring Boot Demo
wget https://github.com/hengyunabc/katacoda-scenarios/raw/master/demo-arthas-spring-boot.jar
java -jar demo-arthas-spring-boot.jar
启动 arthas-boot
wget https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar --target-ip 0.0.0.0
就像基础教程说过的,选择目标进程
查看 JVM 信息
sysprop
- 查看当前 JVM 的系统属性(
System Property
)-
sysprop
打印所有System Properties
- 指定单个 key:
sysprop java.version
- 通过 grep 过滤:
sysprop|grep user
- 设置新的value:
sysprop testKey testValue
-
[图片上传失败...(image-51b975-1590935866588)]
sysenv
-
sysenv
命令查看当前 JVM 的环境属性(System Environment Variables
)
[图片上传失败...(image-e209dc-1590935866588)]
-
也是支持查看单个环境变量值:
sysenv USER
分析线程阻塞
不重启修复BUG
参考
- 官宣-Arthas入门
- Java 诊断工具 Arthas 教程学习笔记