反编译指定已加载类的源码
jad 命令将 JVM 中实际运行的 class 的 byte code 反编译成 java 代码,便于你理解业务逻辑;如需批量下载指定包的目录的 class 字节码可以参考 dump。
在 Arthas Console 上,反编译出来的源码是带语法高亮的,阅读更方便
当然,反编译出来的 java 代码可能会存在语法错误,但不影响你进行阅读理解
查看 JVM 已加载的类信息,“Search-Class” 的简写,这个命令能搜索出所有已经加载到 JVM 中的 Class 信息,这个命令支持的参数有 [d]、[E]、[f] 和 [x:]。
(1)class-pattern 支持全限定名,如 com.taobao.test.AAA,也支持 com/taobao/test/AAA 这样的格式,这样,我们从异常堆栈里面把类名拷贝过来的时候,不需要在手动把/替换为.啦;
(2)sc 默认开启了子类匹配功能,也就是说所有当前类的子类也会被搜索出来,想要精确的匹配,请打开options disable-sub-class true开关;
查看已加载类的方法信息,“Search-Method” 的简写,这个命令能搜索出所有已经加载了 Class 信息的方法信息。
sm 命令只能看到由当前类所声明 (declaring) 的方法,父类则无法看到。
反编译指定已加载类的源码
jad 命令将 JVM 中实际运行的 class 的 byte code 反编译成 java 代码,便于你理解业务逻辑;如需批量下载指定包的目录的 class 字节码可以参考 dump。
在 Arthas Console 上,反编译出来的源码是带语法高亮的,阅读更方便
当然,反编译出来的 java 代码可能会存在语法错误,但不影响你进行阅读理解
Memory Compiler/内存编译器,编译.java文件生成.class。
注意,mc 命令有可能失败(被编译的类依赖了项目中使用到的第三方库)。如果编译失败可以在本地编译好.class文件,再上传到服务器。
加载外部的.class 文件,redefine jvm 已加载的类。
推荐使用 retransform 命令。
redefine 的 class 不能修改、添加、删除类的 field 和 method,包括方法参数、方法名称及返回值。
如果 mc 失败,可以在本地开发环境编译好 class 文件,上传到目标系统,使用 redefine 热加载 class
目前 redefine 和 watch/trace/jad/tt 等命令冲突,以后重新实现 redefine 功能会解决此问题
注意, redefine 后的原来的类不能恢复,redefine 有可能失败(比如增加了新的 field),参考 jdk 本身的文档。
reset命令对redefine的类无效。如果想重置,需要redefine原始的字节码。
redefine命令和jad/watch/trace/monitor/tt等命令会冲突。执行完redefine之后,如果再执行上面提到的命令,则会把redefine的字节码重置。 原因是 jdk 本身 redefine 和 Retransform 是不同的机制,同时使用两种机制来更新字节码,只有最后修改的会生效。
`redefine 的限制`
不允许新增加 field/method
正在跑的函数,没有退出不能生效,比如下面新增加的System.out.println,只有run()函数里的会生效
加载外部的.class文件,retransform jvm 已加载的类。
如果多次执行 retransform 加载同一个 class 文件,则会有多条 retransform entry.
TransformCount 统计在 ClassFileTransformer#transform 函数里尝试返回 entry 对应的 .class 文件的次数,但并不表明 transform 一定成功。
删除指定 retransform en
TransformCount 统计在 ClassFileTransformer#transform 函数里尝试返回 entry 对应的 .class 文件的次数,但并不表明 transform 一定成功。
查看 retransform entry
删除指定 retransform entry
显式触发 retransform
消除 retransform 的影响
如果不清除掉所有的 retransform entry,并重新触发 retransform ,则 arthas stop 时,retransform 过的类仍然生效。
结合 jad/mc 命令使用
上传 .class 文件到服务器的技巧
retransform 的限制
(1)不允许新增加 field/method
(2)正在跑的函数,没有退出不能生效,比如下面新增加的System.out.println,只有run()函数里的会生效.
dump 命令将 JVM 中实际运行的 class 的 byte code dump 到指定目录,适用场景批量下载指定包目录的 class 字节码;如需反编译单一类、实时查看类信息,可参考 jad。
不指定目录加载类的 bytecode
加载类的 bytecode 到 /tmp/output
查看 classloader 的继承树,urls,类加载信息
classloader 命令将 JVM 中所有的 classloader 的信息统计出来,并可以展示继承树,urls 等。
可以让指定的 classloader 去 getResources,打印出所有查找到的 resources 的 url。对于ResourceNotFoundException比较有用。
按类加载类型查看统计信息
按类加载实例查看统计信息
查看 ClassLoader 的继承树
查看 URLClassLoader 实际的 urls
使用 ClassLoader 去查找 resource
使用 ClassLoader 去加载类
统计 ClassLoader 实际使用 URL 和未使用的 URL