Java Instrumentation中retransformClasses为何会静默失败?
Java Instrumentation类重转换时无效字节码静默失败问题
我尝试使用Java Instrumentation进行类重转换,以下代码可正常运行并输出Hello World!!:
public class Main { public static void main(String[] args) throws Throwable { var inst = MyAgent.getInstrumentation(); inst.addTransformer(new ClassFileTransformer() { @Override public byte[] transform(ClassLoader loader, String name, Class<?> c, ProtectionDomain pd, byte[] b) { if (c != Main.class) return null; var cr = new ClassReader(b); var cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); cr.accept(new ClassVisitor(ASM9, cw) { @Override public MethodVisitor visitMethod(int acc, String name, String desc, String sig, String[] exc) { var mv = super.visitMethod(acc, name, desc, sig, exc); if ("foo".equals(name)) { return new MethodVisitor(ASM9, mv) { @Override public void visitCode() { super.visitCode(); visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); visitLdcInsn("Hello "); visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V", false); } }; } return mv; } }, 0); return cw.toByteArray(); } }, true); inst.retransformClasses(Main.class); foo(); } public static void foo() { System.out.println("World!!"); } }
然而,当ClassFileTransformer返回无效字节码或new byte[0]时,重转换会静默失败:既不抛出异常,也无任何变更。
根据Java官方文档描述,若提供无效字节码,retransformClasses方法应抛出异常:
The class file bytes are not checked, verified and installed until after the transformations have been applied, if the resultant bytes are in error this method will throw an exception.
无论在Java Agent外部使用Instrumentation对象,还是将重转换代码放入Agent中,行为完全一致。我测试了以下GraalVM EE版本及OpenJDK,均出现静默失败情况:
java version "17.0.6" 2023-01-17 LTS Java(TM) SE Runtime Environment GraalVM EE 22.3.1 (build 17.0.6+9-LTS-jvmci-22.3-b11) Java HotSpot(TM) 64-Bit Server VM GraalVM EE 22.3.1 (build 17.0.6+9-LTS-jvmci-22.3-b11, mixed mode, sharing)
为何会出现静默失败?是否我的Instrumentation使用方式有误?如何在字节码畸形时触发异常?感谢解答。
(感谢Johannes Kuhn修正了不支持的ASM API用法)
内容的提问来源于Stack Exchange,提问作者Frank Yang
相关产品推荐
相关产品推荐

