2016-11-27 8 views
0

実行時に次のクラスを変更して、各メソッドの最後にインスタンス変数 'c​​ount'の値を出力する必要があります。javasssistを使用したインスタンス変数の印刷

package test.hib.javaassist; 

import java.io.IOException; 

import javassist.CannotCompileException; 
import javassist.ClassPool; 
import javassist.CtClass; 
import javassist.CtMethod; 
import javassist.NotFoundException; 

public class JavaAssistTest { 

    int count; 


    public void doSomething1(){ 
     count++; 
    } 

    public void doSomething2(){ 
     count++; 
    } 

    public void doSomething3(){ 
     count++; 
    } 

    public void doSomething4(){ 
     count++; 
    } 

} 

以下は、javaassistの助けを借りてバイトコードを変更しようとしているメインクラスです。

package test.hib.javaassist; 

import java.io.IOException; 

import javassist.CannotCompileException; 
import javassist.ClassPool; 
import javassist.CtClass; 
import javassist.CtMethod; 
import javassist.NotFoundException; 

public class Main { 

    public static void main(String[] args) throws NotFoundException, CannotCompileException, IOException { 

     ClassPool pool = ClassPool.getDefault(); 
     CtClass cc = pool.get("test.hib.javaassist.JavaAssistTest"); 
     CtMethod[] methods = cc.getDeclaredMethods(); 

     for(CtMethod method : methods){ 
      if(! (method.getName().equals("main"))){ 
       method.insertAfter("{System.out.println(count);}"); 
       //method.insertAfter("System.out.println($type);"); 
      } 
     } 

     cc.writeFile(); 

     System.out.println("Completed editting"); 

     JavaAssistTest test = new JavaAssistTest(); 
     test.doSomething1(); 
     test.doSomething2(); 
     test.doSomething3(); 
     test.doSomething4(); 

     System.out.println("Finished"); 

    } 

} 

現在のところ、それはあなたが私のコードでミスをpointoutことができます私はそれが

Completed editting 
1 
2 
3 
4 
Finished 

を印刷したい

Completed editting 
Finished 

を印刷していますか?

+0

私はクラスが既にロードされていると思いますので、.classファイルへの変更は現在のJVMのランタイムには反映されません。たとえば、次のようにクラスをリロードすることができます。ここで:http://stackoverflow.com/a/3971771/281108 –

+0

hmm .... lil複雑に見えます。私はクラスを読み込む別の方法を試みた。 \t \tクラスtestClass = Loader.getSystemClassLoader()。loadClass( "test.hib.javaassist.JavaAssistTest"); \t \t JavaAssistTestテスト=(JavaAssistTest)testClass.newInstance();しかし、結果に変化はない! – Renjith

+0

クラスが既に読み込まれている場合、クラスをリロードしないことは間違いないでしょう。 –

答えて

1

ここではJavassist APIが少し混乱しています。 writeFileの実装を見てください。 writeFile(".")のショートカットで、クラスをクラスパスではなくプログラムディレクトリに保存します。あなたは、元のクラスファイルをオーバーライドして、このメソッドがしないものを期待します。システムクラスローダーは、更新されたクラスファイルを見つけることができません。

あなたが手動writeFile(String)を使用して、右の場所にクラスファイルを保存したり、あなたのクラスローダが手動でそれをルックアップする前に変更クラスのロードを強制的にcc.toClass()を呼び出すことによって変更されたクラスのロードを強制することができます。

+0

ありがとうございました! cc.toClass()が機能しました。最後に、Tomcat Serverにデプロイされたアプリケーションでこれを使用する必要があります。しかし、アプリケーションサーバー上で実行されているアプリケーションには、同じことが適用できないことがJavaの文書に示されています。私は 'toClass(java.lang.ClassLoader loader)'を使ってみる必要があります。 – Renjith

関連する問題