跳到主要内容
JackSparrow414
返回

Arthas

本文导航

展开本文导航

Arthas

启动/重进入

  1. 启动

    # 一般arthas的jar包下载都会放在默认当前位置下,如果当前为root角色
    # cd ~
    # cd .arthas/lib/3.4.3/arthas
    # 需要管理权限才可以启动,也可以进入 cd .arthas/lib/版本/arthas,再执行
    sudo java -jar arthas-boot.jar
  2. 重进入

    重进入是指,退出终端之后,下次想要再次连接到arthas内

    telnet localhost 3658

启动常见问题

  1. Unable to open socket file: target process not responding or HotSpot VM not loaded

    官方解答地址

    • 先试着能不能用jstack pid 连上,如果jstack pid连接也报这个错,那基本可以去各大搜索引擎查找问题了
    • 如果最终你试了N种方法都不行,比如网上最多的回答/tmp/hsperfdata_$USER消失引起的(这里我也查了,是存在的),那么你可以试着更新下机器上的JDK。我机器上原来的open-jdk版本是1:1.8.0.252.b09-3.el8_2,怎么都不行。更新到java-1.8.0-openjdk-1:1.8.0.265.b01-0.el8_2.x86_64就可以了

以下是本人在实际开发中用到的使用场景,更多场景可见Arthas官方文档

生产环境修改代码、更新

实际开发很容易遇到的场景:

​ 生产环境出现紧急问题。在线下修改代码,并测试通过。这时可能只修改了几个文件,或者只加了几行代码。那么生产环境的jar包要重新停掉、并重新打包、部署、发布。影响的范围就更大了。这时热更新.class文件就可以了

arthas为我们提供了一站式的解决步骤,从读取.class文件----->编译成.java文件------->修改.java文件------>将修改后的.java文件编译成新的.class文件-------->将新的.class文件通过classloader加载进JVM内

实际场景中,前面的步骤其实都可以从线下做完,将线下编译的.calss文件传到服务器上,并执行最后一步,加载进JVM内即可。详细步骤参考官方文档

这里使用arthas的一系列命令演示线上问题修复过程

场景

  1. 首先,使用sc命令找到要修改的类.sc全称-search class, -d表示detail,主要是为了获取classLoader的hash值

    sc -d *UserController*

Arthas sc 命令输出 SysController 的类与类加载器信息

这里可以看到详细的类的信息

  1. 拿到类的classloader的哈希值,就开始修改代码

  2. 修改代码的第一步,首先使用jad命令将.class文件反编译为.java文件才行。-c 指定这个类的classloader的哈希值,—source-only只显示源码,最后是文件反编译之后的存放路径

    jad -c 49c2faae --source-only *SysUserController* > /xxx要保存的具体路径/SysUserController.java

Arthas jad 命令反编译得到的 SysController Java 源码 Arthas 将 jad 反编译结果写入 Java 文件的命令

截取了部分代码,如上。可以看到,已经拿到了Java代码

  1. 进行修改代码,这里只加入一句代码

    System.pit.println("有人登录了---");

修改后的登录方法添加 System.out.println 输出

  1. 修改完毕之后,使用mc(Memory Compiler)命令,将Java文件重新编译为.class文件. -d 指定编译之后的.class文件的位置,最后一个参数为刚才修改的Java文件的位置

    mc -c 49c2faae -d /tmp /xxx具体的路径/SysUserController.java

Arthas mc 命令将修改后的 Java 文件编译为 class 文件

  1. 拿到.class文件之后,重新加载进JVM内即可.使用redefine

    redefine -c 49c2faae /xxx具体.class文件的路径/SysUserController.class

Arthas redefine 命令提示类重新加载成功

提示加载成功

  1. 重新登录,查看修改是否生效 重新登录后的控制台日志显示新增输出生效

    可以看到,确实是生效了

实时修改生产环境日志级别

生产环境日志一般为warn、error级别的,对于debug日志一般看不到,那么出问题的时候,一些日志,在写代码的时候会被记录在debug日志中,而此时日志级别又很高。那么迫切需要调整日志级别

场景

  1. 查看当前应用日志级别

    logger

Arthas logger 命令显示当前日志级别为 INFO

可以看到目前日志级别为INFO

  1. 修改日志级别

    logger -c 49c2faae --name ROOT --level debug

Arthas logger 命令将日志级别修改为 DEBUG 的结果

可以看到这里的日志修改成功了

注意事项

redefine命令使用之后,再使用jad命令会使字节码重置,恢复为未修改之前的样子。官方关于redefine命令的说明

便捷地修改JVM参数

一般的查看JVM参数,使用Java自带的jinfo命令即可.例如

查看某一个Java应用的JVM参数

# 找到Java应用的jps - java process status
jps -l

jps -l 输出中的 Java 进程 ID 与启动类或 JAR

再使用jinfo

# 查看所有参数配置情况
jinfo 16018
# 查看某个参数的配置情况
jinfo -flag HeapDumpOnOutOfMemoryError 16018
# 帮助
jinfo -h

在arthas中,直接一个单词即可.打印出JVM的参数配置情况

vmoption

Arthas vmoption 命令列出 JVM 参数及当前值修改JVM参数,这里设置JVM出现OutOfMemoryError的时候,自动dump堆快照

vmoption HeapDumpOnOutOfMemoryError true

Arthas 将 HeapDumpOnOutOfMemoryError 从 false 修改为 true

使用jinfo则是

jinfo -flag +HeapDumpOnOutOfMemoryError 16018

+代表开启,-代表关闭

其他命令

全部命令可参考Arthas官方文档

更好用的工具

去哪的Java问题排查工具Bistoury是以Arthas基础进行开发的,提供了图形界面操作,很方面。个人觉得最赞的功能是可以在生产环境debug的功能。项目GitHub地址


分享本文:

上一篇
Java中的锁(三)结合Condition实现等待通知
下一篇
JVM笔记(一)

评论

欢迎提问、纠错和分享经验。发表评论需要登录 GitHub;中英文版本共享评论。

评论仅在正式网站开放。