行の前に sleep() を呼び出すなど、クラスを動的に変更しようとしていました。メソッドを使用して実行時にエージェントを jvm にアタッチしましたAttach
。次に、jvm からターゲット クラスを取得し、それを変更しました (呼び出す行を追加しますsleep()
)。そして、クラスエラーを再定義しました。私は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);
}
}