gpt4 book ai didi

java - Failed to redefine class 当我尝试重新转换类时

转载 作者:行者123 更新时间:2023-11-29 05:38:27 26 4
gpt4 key购买 nike

我试图动态修改类,例如在一行之前调用 sleep() 。我在运行时使用 Attach 方法将代理附加到 jvm。然后我从 jvm 得到目标类,并修改它(添加一行调用 sleep())。我得到了 redine 类错误。我正在使用 JDK1.6。我正在使用 ASM 核心 API 来修改类。错误:

Caused by: java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)
at sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
at sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:124)

ASM代码有问题吗?实际上我的 ASM 代码完成了它的工作(添加一行来调用 sleep())。当前的 jvm 不支持重新转换类吗?似乎未能执行 retransformClasses()retransformClasses()是否不支持ASM操作(在方法中添加一行调用sleep())?有任何想法吗?谢谢

编辑:我要修改的类:

import java.util.concurrent.TimeUnit;

public class Person {
public String name = "abc";
public String address = "xxxxx" ;

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void sayHello() throws InterruptedException {
System.out.println("aaaaaaaaaa");
System.out.println("Hello World!");
TimeUnit.SECONDS.sleep(120);
System.out.println("dd");
}
public void sayHello2() {
System.out.println("aaaaaaaaaa1");
System.out.println("Hello World!2");
}

public static void main (String args[]) {
try {
Person p = new Person();
p.sayHello(); // linenumber #9. A line to call Sleep() should be added before #here.

p.sayHello2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

我的 ASM 代码:

public void visitMethodInsn(int arg0, String arg1, String arg2, String arg3) {

Label la=new Label();
mv.visitLabel(la);
int linenumber=la.getOffset();
if(linenumber==9) {
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/util/concurrent/TimeUnit", "SECONDS", "Ljava/util/concurrent/TimeUnit;");
mv.visitLdcInsn(new Long("5"));
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/concurrent/TimeUnit", "sleep", "(J)V");

super.visitMethodInsn(arg0, arg1, arg2, arg3);

}
}

最佳答案

还没有看你的代码,我想我可以提出一些建议。首次加载类时,除了存储类的字节码外,JVM 还具有表,用于跟踪每个类中字段的类型和方法的签名。

您看到的错误表明类已加载,此签名信息已存储,然后您尝试在此之后添加该方法。

如果您改为将代理 jar 放到命令行上,您可以在类首次加载之前执行操作。如果您在签名信息被存储之前添加您的方法,您应该是好的。

如果您必须在进程已经启动后连接代理,您可以转换类,但您可能只能在不更改字段集、它们的类型、方法或它们的情况下转换它签名。换句话说,您可以更改字节码,但不能使先前存储的元信息无效。

关于java - Failed to redefine class 当我尝试重新转换类时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18605025/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com