arthas-boot.jar 或者 as.sh 的版本: 3.4.1arthas-boot的版本: 3.4.1public class Test {
public static void main(String[] args) throws InterruptedException {
Test test = new Test();
while (true) {
try {
AtomicInteger i = new AtomicInteger();
Runnable runnable = () -> {
i.getAndIncrement();
};
} catch (NoClassDefFoundError e) {
e.printStackTrace();
Thread.sleep(2000);
}
}
}
}
运行上述代码,并用arthas attach,然后使用命令 jad package.Test.
虽然可以正确反编译类的内容,但上述程序开始抛出异常。
java.lang.NoClassDefFoundError: cn/willingxyz/javaagent/Test$$Lambda$1
at cn.willingxyz.javaagent.Test$$Lambda$1/1156060786.get$Lambda(Unknown Source)
at cn.willingxyz.javaagent.Test.main(Test.java:18)
可能和 https://bugs.openjdk.java.net/browse/JDK-8145964 这个bug有关,不过jad命令(和其他相关命令)是否能够绕开该bug。
这两个issue应该是类似问题: https://github.com/alibaba/arthas/issues/747 , https://github.com/alibaba/arthas/issues/968
这个redefine的bug也可以参考下: https://zhuanlan.zhihu.com/p/91756092 。
jdk的bug没有太好的办法,只能升到高版本的。
这两个issue应该是类似问题: #747 , #968
这个redefine的bug也可以参考下: https://zhuanlan.zhihu.com/p/91756092 。
jdk的bug没有太好的办法,只能升到高版本的。
处理lambda类的时候,能够忽略这个lambda类吗,至少不要影响到应用吧
这两个issue应该是类似问题: #747 , #968
这个redefine的bug也可以参考下: https://zhuanlan.zhihu.com/p/91756092 。
jdk的bug没有太好的办法,只能升到高版本的。处理lambda类的时候,能够忽略这个lambda类吗,至少不要影响到应用吧
jad命令实际上是触发了一次 retransform ,并没有做其它的修改。 另外,在jdk11上没有这个问题。 还有貌似不是所有有 lambda的都会出现这个问题。 所以也没办法为特定的情况处理。
这两个issue应该是类似问题: #747 , #968
这个redefine的bug也可以参考下: https://zhuanlan.zhihu.com/p/91756092 。
jdk的bug没有太好的办法,只能升到高版本的。处理lambda类的时候,能够忽略这个lambda类吗,至少不要影响到应用吧
jad命令实际上是触发了一次 retransform ,并没有做其它的修改。 另外,在jdk11上没有这个问题。 还有貌似不是所有有 lambda的都会出现这个问题。 所以也没办法为特定的情况处理。
我看了源码,反编译某个类的时候,也会retransform它的内部类,这些内部类里就包括了lambda类。
所以,retransform的时候是否能忽略这些lambda类
原始的 Test.class类里,引用的lambda类是 lambda$0 。
#66 = Methodref #1.#67 // Test.lambda$0:(Ljava/util/concurrent/atomic/AtomicInteger;)V
#67 = NameAndType #49:#50 // lambda$0:(Ljava/util/concurrent/atomic/AtomicInteger;)V
#68 = MethodHandle #6:#66 // invokestatic Test.lambda$0:(Ljava/util/concurrent/atomic/AtomicInteger;)V
调试的栈也是 lambda$0 :
Thread [Thread-0] (Suspended (breakpoint at line 13 in Test))
Test.lambda$0(AtomicInteger) line: 13
1620303253.run() line: not available
Thread.run() line: 748
但是抛出异常的栈显示:
java.lang.NoClassDefFoundError: Test$$Lambda$1
at Test$$Lambda$1/1418481495.get$Lambda(Unknown Source)
at Test.main(Test.java:12)
可见的确是jdk bug问题。
jdk8 和jdk11的不同之处,应该是 jdk11在 retransform lambda类时,直接抛出了异常。而jdk8还是正常处理,然后导致新的字节码出错。
java.lang.instrument.UnmodifiableClassException: null
at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:167)
at com.taobao.arthas.core.util.InstrumentationUtils.retransformClasses(InstrumentationUtils.java:25)
at com.taobao.arthas.core.command.klass100.JadCommand.processExactMatch(JadCommand.java:166)
at com.taobao.arthas.core.command.klass100.JadCommand.process(JadCommand.java:147)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:82)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:18)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:111)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:108)
at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:385)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
实际上 jdk11,会retransform lambda类时,没回调 ClassFileTransformer 就抛出异常了。 也就是说 jdk11下面,拿不到 lambda类的字节码。
但是jdk8下可以拿到,但是会导致应用出错。 应用实际是先抛出 ClassNotFoundException ,然后第二次就会变成 NoClassDefFoundError 。
java.lang.NoClassDefFoundError: Test$$Lambda$1
at Test$$Lambda$1/1418481495.get$Lambda(Unknown Source)
at Test.main(Test.java:12)
Caused by: java.lang.ClassNotFoundException: Test$$Lambda$1
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 2 more
java.lang.NoClassDefFoundError: Test$$Lambda$1
at Test$$Lambda$1/1418481495.get$Lambda(Unknown Source)
at Test.main(Test.java:12)
目前而言,最好是直接不 retransform lambda类。
同样 watch等命令也会有类似问题,已处理。 watch Test* *
Most helpful comment
同样 watch等命令也会有类似问题,已处理。
watch Test* *