Arthas 应用诊断利器学习及使用(十) 类命令jad,dump

411 阅读2分钟

这是我参与更文挑战的第8天,活动详情查看: 更文挑战

本文内容基于arthas 3.5.2 版本,介绍类命令jad,dump的使用及实现

一.jad命令

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

参数名称参数缩写参数说明必填项
class-pattern名称表达式匹配必填
method-pattern方法名表达式匹配可选
--regex-E开启正则表达式匹配,默认为通配符匹配。可选
--code-c指定class的 ClassLoader 的 hashcode可选
--classLoaderClass指定执行表达式的 ClassLoader 的 class name可选
--hideUnicode不显示unicode码,默认为false可选
--source-only输出只显示源代码,默认为false可选

文件位于com.taobao.arthas.core.command.klass100.JadCommand.java

image.png

指定执行表达式的 ClassLoader 的 class name, 对于只有唯一实例的ClassLoader才可以通过--classLoaderClass指定class name。

只有匹配到唯一的ClassLoader实例时才能正常工作,当存在多个的情况下需要通过-c指定hashcode SearchUtils.searchClassOnly()搜索class,并根据E来判断是否开启正则匹配。

没有匹配到class,processNoMatch()报错提示, 匹配到多个时processMatches()提示使用jad -c 来确定唯一的class 匹配到唯一的class,查找内部类,按照(主类名$*),若不存在内部类withInnerClasses则为查到的唯一class作为参数,执行processExactMatch()

InstrumentationUtils.retransformClasses(ClassFileTransformer transformer, boolean canRetransform) 注册ClassFileTransformer实例,注册多个则会按照注册顺序进行调用。

所有的类被加载完毕之后会调用ClassFileTransformer实例,相当于它们通过了redefineClasses方法进行重定义。布尔值参数canRetransform决定这里被重定义的类是否能够通过retransformClasses方法进行回滚。

inst.retransformClasses(clazz)回滚。inst.removeTransformer()删除ClassFileTransformer实例。

将class字节码写入文件中用于编译。 ClassDumpTransformer transformer = new ClassDumpTransformer(allClasses)文件写入arthas日志文件所在路径。

Decompiler.decompile(classFile.getAbsolutePath(), methodName, hideUnicode)反编译,使用Cfr库反编译,hideUnicode默认为false,会显示初始编码,例如:世界反编译后为\u4e16\u754c(hideUnicodetrue正常显示文字?) Pattern.compile("(?m)^/\\*\\s*\\*/\\s*$" + System.getProperty("line.separator"))删除反编译后的注释。

--source-only反编译时只显示源代码,默认为false,反编译结果里会带有ClassLoader信息 ClassUtils.createSimpleClassInfo(c) ClassUtils.getCodeSource(c.getProtectionDomain().getCodeSource())

二.dump命令

dump 已加载类的 bytecode 到特定目录

参数名称参数缩写参数说明必填项
class-pattern外部的.class文件的完整路径,支持多个必填
--classLoaderClass指定执行表达式的 ClassLoader 的 class name可选
--code-c指定class的 ClassLoader 的 hashcode可选
--regex-E开启正则表达式匹配,默认为通配符匹配可选
--directory-d为class文件输出设置文件路径可选
--limit-ldump 的class文件个数限制,默认为50,原描述为5有误。可选

文件位于com.taobao.arthas.core.command.klass100.DumpClassCommand.java

image.png

SearchUtils.searchClass根据类的全限定名,classloader的hashcode,正则匹配获取。 若没有找到对应的class则执行processNoMatch方法直接提示未找到。

若匹配到的class数大于limit,则进入processMatches(process, matchedClasses)方法,提示使用--limit配置参数,显示更多的内容。并返回简单的class信息,只显示classLoader名和classLoader的hashcode的列表。

若没有超出限制,则执行processMatch(process, effect, inst, matchedClasses)方法。通过dump(inst, matchedClasses)方法dump具体的class文件。自定义ClassDumpTransformer类实现接口ClassFileTransformer中的transform方法。最后获取dump结果。