2

行の前に 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);

    }
}
4

1 に答える 1