Arthas: 当使用了arthas的其它指令时,jad出来的是原始的源码还是被增强过的?

Created on 20 Dec 2018  ·  7Comments  ·  Source: alibaba/arthas

当使用了arthas的其它指令时,jad出来的是原始的源码还是被增强过的?

question-answered

Most helpful comment

这个事情有点复杂。

  • watch/jad 等命令实际上都是基于java.lang.instrument.ClassFileTransformer来做的。想要对字节码做修改,就要显式触发jvm的Transform机制
  • jvm会把这些用户插入的ClassFileTransformer一个个依次执行,最终得到结果
  • ClassDumpTransformer.transform(ClassLoader, String, Class<?>, ProtectionDomain, byte[])这个子函数可以获取到类的实际字节码,watch/jad 都是在这里做的工作。
  • watch/jad 都是插入一个自己的ClassFileTransformer,然后把这个ClassFileTransformer删除掉

  • 所以,实际上目前这些命令会有互相有影响的。比如用户A在watch,另个一个用户B执行了jad,则用户A的watch插入的代码就没有了。(因为jvm重新Transform,然而用户A watch插入的Transformer已经remove掉了)
  • 那为什么多个wathch,可以同时工作?因为watch/monitor这些命令会保存一个cache:com.taobao.arthas.core.advisor.Enhancer.classBytesCache,在下一次Transform时,优先从cache里取。

所以总结,这是个复杂的问题,arthas里目前的实现比较混乱。就jad这命令本身来说,它获取不到watch/monitor等命令插入的代码,还会把这些命令插入的代码清理掉。

All 7 comments

这个事情有点复杂。

  • watch/jad 等命令实际上都是基于java.lang.instrument.ClassFileTransformer来做的。想要对字节码做修改,就要显式触发jvm的Transform机制
  • jvm会把这些用户插入的ClassFileTransformer一个个依次执行,最终得到结果
  • ClassDumpTransformer.transform(ClassLoader, String, Class<?>, ProtectionDomain, byte[])这个子函数可以获取到类的实际字节码,watch/jad 都是在这里做的工作。
  • watch/jad 都是插入一个自己的ClassFileTransformer,然后把这个ClassFileTransformer删除掉

  • 所以,实际上目前这些命令会有互相有影响的。比如用户A在watch,另个一个用户B执行了jad,则用户A的watch插入的代码就没有了。(因为jvm重新Transform,然而用户A watch插入的Transformer已经remove掉了)
  • 那为什么多个wathch,可以同时工作?因为watch/monitor这些命令会保存一个cache:com.taobao.arthas.core.advisor.Enhancer.classBytesCache,在下一次Transform时,优先从cache里取。

所以总结,这是个复杂的问题,arthas里目前的实现比较混乱。就jad这命令本身来说,它获取不到watch/monitor等命令插入的代码,还会把这些命令插入的代码清理掉。

我们在调试的时候,担心注入的代码可能影响业务代码,所以想要看到注入后的结果。现在jad不支持的话,除了改arthas-core.jar然后手动输出class文件,就别无他法了。

可以用这个工具: https://github.com/hengyunabc/dumpclass

可以用这个工具: https://github.com/hengyunabc/dumpclass

谢谢!

发现原来arthas自带了自动dump下来class文件的功能,只要把globaloptions的isdump调成true就可以了。

发现原来arthas自带了自动dump下来class文件的功能,只要把globaloptions的isdump调成true就可以了。

https://alibaba.github.io/arthas/dump.html ,这个不一定完全准确,参考上面的说明。

需要绝对准确的dump,可以用上面的 dumpclass 工具。

不执行jad,直接执行watch也是一样的。
会不会是下面2个参数的设置问题? 需要特别设置吗?我测试的是servlet
--telnet-port The target jvm listen telnet port, default 3658
--http-port The target jvm listen http port, default 8563

Was this page helpful?
0 / 5 - 0 ratings