Alibaba Arthas

Alibaba Arthas

基于arthas 3.4.6

Arthas是Alibaba开源的Java诊断工具

可以用来解决

  1. 查看class 的加载路径,排除ClassLoader 双向委派存在的问题

  2. 程序在线反编译,与热更新

  3. 监控到JVM的实时运行状态(线程状态,程序热点,内存情况)

优点:

  1. 兼容分享jvisualvm dump文件

  2. 最低支持JDK6与Linux&Mac&Windows运行(推荐不低于7)

  3. 命令交互,Tab 提示功能完善

  4. 彩色界面观察更直观

更多使用参考Arthas官方文档

常用功能分享

下载使用

官网教程链接

使用退出

使用

java -jar arthas-boot.jar 

选择程序

退出

exit\quit

在这里插入图片描述

基础常用命令

命令界面支持常用的操作系统终端命令

help 帮助命令

pwd 当前路径
在这里插入图片描述

echo

类似Linux echo 但不支持输出变量

Cat

输出文件内容

cltr+l

Cls 清除终端的数据信息

history

历史输出命令

Class相关

SC 查看** JVM **已加载的类信息

sc “Search-Class” _ 的简写 用来查看 JVM 已加载的类信息 _

参数说明

参数名称参数说明
class-pattern类名表达式匹配
[d]输出当前类的详细信息,包括这个类所加载的原始文件来源、类的声明、加载的ClassLoader等详细信息。 如果一个类被多个ClassLoader所加载,则会出现多次
[E]开启正则表达式匹配,默认为通配符匹配
[f]输出当前类的成员变量信息(需要配合参数-d一起使用)
[x:]指定输出静态变量时属性的遍历深度,默认为 0,即直接使用 toString 输出
[c:]指定class的 ClassLoader 的 hashcode
[classLoaderClass:]指定执行表达式的 ClassLoader 的 class name
[n:]具有详细信息的匹配类的最大数量(默认为100)

class-pattern

支持 com.xxx.xx ** com/xxx/xx **** 限定名方式 与 **** *xxx **** 通配符 模糊匹配**

-d 展示 类的详情

 sc -d demo.\* (前提demo包下仅有MathGame 一个Class)
 class-info demo.MathGame (全名称)
 code-source /root/arthas-demo.jar (加载路径)
 name demo.MathGame (全名称)
 isInterface false (是否接口)
 isAnnotation false (是否注解)
 isEnum false (是否枚举)
 isAnonymousClass false (是否匿名类)
 isArray false (是否数组)
 isLocalClass false (是否局部类)
 isMemberClass false (是否成员类)
 isPrimitive false (是否基本类型)
 isSynthetic false (是否编译器引入)
 simple-name MathGame (是否注解)
 modifier public (可见性)
 annotation (包含的注解)
 interfaces (实现的接口)
 super-class +-java.lang.Object
 class-loader +-jdk.internal.loader.ClassLoaders$AppClassLoader@c387f44
 +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@3313bcd7
 classLoaderHash c387f44

 Affect(row-cnt:1) cost in 6 ms.
 -f 展示类中字段详情配合-d
 class-info demo.MathGame
 code-source /root/arthas-demo.jar
 name demo.MathGame
 isInterface false
 isAnnotation false
 isEnum false
 isAnonymousClass false
 isArray false
 isLocalClass false
 isMemberClass false
 isPrimitive false
 isSynthetic false
 simple-name MathGame
 modifier public
 annotation
 interfaces
 super-class +-java.lang.Object
 class-loader +-jdk.internal.loader.ClassLoaders$AppClassLoader@c387f44
 +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@3313bcd7
 classLoaderHash c387f44
 fields name random
 type java.util.Random
 modifier private,static
 value java.util.Random@459639f
 name illegalArgumentCount
 type int
 modifier private
 Affect(row-cnt:1) cost in 4 ms. 

输出当前类的详细信息,包括这个类所加载的原始文件来源、类的声明、加载的ClassLoader等详细信息。如果一个类被多个ClassLoader所加载,则会出现多次(仅限于此类被继承 存在子类 才可能被CLassLoder 加载多次)

展示此类的所有子类信息

sc 接口/抽象类

sc java.util.Map
 com.sun.crypto.provider.SunJCE
 com.sun.security.sasl.Provider
 com.sun.security.sasl.gsskerb.JdkSASL
 java.lang.ProcessEnvironment$StringEnvironment
 java.security.AuthProvider
 java.security.Provider
 java.util.AbstractMap
 java.util.Collections$EmptyMap
 java.util.Collections$SingletonMap
 java.util.Collections$SynchronizedMap
 java.util.Collections$UnmodifiableMap
 java.util.EnumMap
 java.util.HashMap
 java.util.Hashtable
 java.util.IdentityHashMap
 java.util.ImmutableCollections$AbstractImmutableMap
 java.util.ImmutableCollections$MapN
 java.util.LinkedHashMap
 java.util.Map
 java.util.NavigableMap
 java.util.Properties
 java.util.SortedMap
 java.util.TreeMap
 java.util.WeakHashMap
 java.util.concurrent.ConcurrentHashMap
 java.util.concurrent.ConcurrentMap
 java.util.concurrent.ConcurrentNavigableMap
 java.util.concurrent.ConcurrentSkipListMap
 java.util.jar.Attributes
 org.jcp.xml.dsig.internal.dom.XMLDSigRI
 sun.net.www.http.KeepAliveCache
 sun.nio.cs.StandardCharsets$Aliases
 sun.nio.cs.StandardCharsets$Cache
 sun.security.ec.SunEC
 sun.security.jca.ProviderList$1
 sun.security.jgss.SunProvider
 sun.security.pkcs11.SunPKCS11
 sun.security.provider.Sun
 sun.security.provider.certpath.ldap.JdkLDAP
 sun.security.rsa.SunRsaSign
 sun.security.smartcardio.SunPCSC
 sun.security.ssl.SunJSSE
 sun.util.PreHashedMap
 Affect(row-cnt:43) cost in 9 ms. 

SM 查看已加载类的方法信息

“Search-Method” 的简写,这个命令能搜索出所有已经加载了 Class 信息的方法信息。(只能看到由当前类所声明 (declaring) 的方法,父类则无法看到)

参数信息

sc [-d 展示详情] classFullName [methodName 仅展示具体方法]

在这里插入图片描述

sm com.XX 会输出XX 以及子类的所有方法信息,如 sm java.util,Map 会展示出Map所有子类方法信息。故类名尽可能具体

Class 在线编译 & 反编译 & 热更新

jad 反编译

反编译指定已加载类的源码

其他离线反编译工具

Jad classFullName [methodName 特定函数] [–source-only 仅显示源码剔除 ClassLoader]

[arthas@7192]$ jad demo.MathGame
 ClassLoader:
 +-sun.misc.Launcher$AppClassLoader@18b4aac2
 +-sun.misc.Launcher$ExtClassLoader@78308db1
 Location:
 /E:/workspace/framework/arthas/demo/target/classes/
 /\*
 Decompiled with CFR.

 \*/

 package demo;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
 import java.util.concurrent.TimeUnit;
 public class MathGame {
 private static Random random = new Random();
 private int illegalArgumentCount = 0;
public static void main(String[] args) throws InterruptedException {
 MathGame game = new MathGame();
 while (true) {
 game.run();
 TimeUnit.SECONDS.sleep(1L);
 }
}

public void run() throws InterruptedException {
 try {
 int number = random.nextInt() / 10000;
 List<Integer> primeFactors = this.primeFactors(number);
 MathGame.print(number, primeFactors);
 }
 catch (Exception e) {
 System.out.println(String.format("illegalArgumentCount:%3d, ", this.illegalArgumentCount) + e.getMessage());
 }
}

public static void print(int number, List<Integer> primeFactors) {
 StringBuffer sb = new StringBuffer(number + "=");
 for (int factor : primeFactors) {
 sb.append(factor).append('\*');
 }
 if (sb.charAt(sb.length() - 1) == '\*') {
 sb.deleteCharAt(sb.length() - 1);
 }
 System.out.println(sb);
}

public List<Integer> primeFactors(int number) {
 if (number < 2) {
 ++this.illegalArgumentCount;
 throw new IllegalArgumentException("number is: " + number + ", need >= 2");
 }
 ArrayList<Integer> result = new ArrayList<Integer>();
 int i = 2;
 while (i <= number) {
 if (number % i == 0) {
 result.add(i);
 number /= i;
 i = 2;
 continue;
 }
 ++i;
 }
 return result;
}
 }

|—

MC 内存编译器

Memory Compiler/ 内存编译器,编译.java 文件生成.class_。_

mc [-c 指定具体的classLoder(classLoad hashCode)] [-d 输出目录 默认当前目录]源文件1 [源文件2]

在这里插入图片描述

Retransform 重新加载 Class

加载外部的 .class 文件, retransform jvm 已加载的类。

retransform 在不重启的状态下,同一个Class 每次加载都会记录一条版本信息,JVM 加载的信息以日志记录的最大ID 为准

加载新的 Class

retransform filePath 

加载class文件并重新加载
在这里插入图片描述

展示替换的版本信息

Arthas 重启后所有的信息将不会保留

retransform -l 

在这里插入图片描述

版本信息删除

全删除

| PowerShell

retransform --deleteAll

删除特定版本

| PowerShell

retransform -d ID

基于历史记录刷新

| PowerShell

retransform --classPath classFullName[1…N]

此命令会查找历史信息中ID 最大值的class信息 ,存在的时 使用此版本的class信息替换JVM 中Class信息。若历史不存在,则回复程序原Class 中的逻辑

redefine 不可回退的热更新

其功能与 retransform功能相同,但是更新后无法回退

redefine classFilePath

| PowerShell

redefine /tmp/Test.class

推荐使用 retransform

新增日志的热更新示例
在这里插入图片描述

注意项

JDK 版本

Arthas 使用的 JDK与调试程序使用的JDK 相同(尽管避免Arthas 使用自动推断存在错误)

链接成功(高版本链接低版本 )

在这里插入图片描述

链接失败(arthas jdk 低于目标版本会失败)

在这里插入图片描述

补充文档

  1. JDWP 协议及实现 – IBM Developer
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值