We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
出现这个异常的原因是很明确的,在更新字节码时,增加/删除了field。可能有下面的原因:
JDK的bug,尽量用最新的JDK版本,特别是JDK8
比如: redefine热更新报错 #969 (comment)
其它的java agent修改了字节码,增加了 field。
比如jacoco,这个代码测试覆盖率工具,它会在类里增加一个static field来记录执行信息。
jacoco
其它的java agent修改了字节码,但是在retransform时,生成同样的字节码
retransform
比如skywalking: 无法trace 和watch加载skywalking7 的jar中的类方法 #1141
在执行arthas redefine/retransform命令时,用户自己想替换的字节码有修改
redefine
从JDK 1.5起,有一套ClassFileTransformer的机制,Java Agent通过Instrumentation注册ClassFileTransformer,那么在类加载或者retransform时就可以回调修改字节码。
ClassFileTransformer
Instrumentation
显然,在Arthas里,要增强的类是已经被加载的,所以它们的字节码都是在retransform时被修改的。 通过显式调用Instrumentation.retransformClasses(Class<?>...)可以触发回调。
Instrumentation.retransformClasses(Class<?>...)
Arthas里字节码相关的命令watch/trace/stack/tt/dump/jad/retransform等命令都是通过ClassFileTransformer来实现的。
watch
trace
stack
tt
dump
jad
ClassFileTransformer的接口如下:
public interface ClassFileTransformer { byte[] transform( ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException;
简而言之:
transform
byte[]
retransformClasses
所以,重点结论来了:
class redefinition failed: attempted to change the schema (add/remove fields)
options dump true
arthas-class-dump
The text was updated successfully, but these errors were encountered:
我现在遇到个问题, docker里安装1.8.0_212版本的JDK,arthas3.5.5版本 exec到docker里进入arthas,执行watch命令 输出class redefinition failed: attempted to change the schema (add/remove fields) 异常。。 watch和trace都会,按说这两个命令不会更改到字节码。jad对应的方法后也不是反编译的源码,方法体不见了,输出了return (List)delegate$kilt9k0.intercept(this, new Object[0], (Callable<?>)new auxiliary.kY2cigI3(this), cachedValue$0JsIgyaN$ufneft0); 有人遇到过没有
return (List)delegate$kilt9k0.intercept(this, new Object[0], (Callable<?>)new auxiliary.kY2cigI3(this), cachedValue$0JsIgyaN$ufneft0);
Sorry, something went wrong.
@sohouse 试下最新版本arthas,jdk8也试下最新的。
@hengyunabc 您好,项目中用了jacoco 的javaagent,有什么办法继续用redefine/retransform命令吗?
No branches or pull requests
结论
出现这个异常的原因是很明确的,在更新字节码时,增加/删除了field。可能有下面的原因:
JDK的bug,尽量用最新的JDK版本,特别是JDK8
比如: redefine热更新报错 #969 (comment)
其它的java agent修改了字节码,增加了 field。
比如
jacoco
,这个代码测试覆盖率工具,它会在类里增加一个static field来记录执行信息。其它的java agent修改了字节码,但是在
retransform
时,生成同样的字节码比如skywalking: 无法trace 和watch加载skywalking7 的jar中的类方法 #1141
在执行arthas
redefine
/retransform
命令时,用户自己想替换的字节码有修改理解ClassFileTransformer机制
从JDK 1.5起,有一套
ClassFileTransformer
的机制,Java Agent通过Instrumentation
注册ClassFileTransformer
,那么在类加载或者retransform
时就可以回调修改字节码。显然,在Arthas里,要增强的类是已经被加载的,所以它们的字节码都是在
retransform
时被修改的。通过显式调用
Instrumentation.retransformClasses(Class<?>...)
可以触发回调。Arthas里字节码相关的命令
watch
/trace
/stack
/tt
/dump
/jad
/retransform
等命令都是通过ClassFileTransformer
来实现的。ClassFileTransformer
的接口如下:简而言之:
transform
函数传入字节码byte[]
,再返回新的字节码byte[]
ClassFileTransformer
可能有多个,那么在JVM里运行的字节码里,可能是被多个ClassFileTransformer
处理过的。retransformClasses
之后,多个agent注册的多个ClassFileTransformer
会被依次回调,上一个处理的字节码传递到下一个。所以不能保证这些
ClassFileTransformer
第二次执行会返回同样的结果。所以,重点结论来了:
ClassFileTransformer
要支持多次执行,每次生成同样的结果。ClassFileTransformer
增加field不?可以的,但要保证第一条。ClassFileTransformer
每次生成同样的结果,就很容易出现class redefinition failed: attempted to change the schema (add/remove fields)
。ClassFileTransformer
之后,做完transform
之后(可能修改了schema,add/remove fields),它把注册的ClassFileTransformer
删掉了。那么当别的agent再次触发retransform
时,就会出错了。排查
transform
之后,生成的字节码是怎样的options dump true
的开关,打开之后,arthas会把经过自己ClassFileTransformer
处理过的字节码保存到arthas-class-dump
目录,方便分析排查The text was updated successfully, but these errors were encountered: