Javaプログラミング/Javaプログラミング関連情報

クラスファイルを強制変換する(2ページ目)

Javassistで、クラスファイル変換を使ってクラスの中身を変えてしまいましょう。

執筆者:掌田 津耶乃

クラスを操作してみる


では、実際に簡単なクラスを用意して操作をしてみることにしましょう。ここでは、以下のようなごくシンプルなBeanクラスを作成し、これを操作してみることにします。

package jp.tuyano.jasample;

public class TestBean {
 public String testfield = "helo";
 
 public void test(){
  System.out.println(testfield);
 }
}


これをコンパイルしクラスファイルを作成しておきます。このクラスファイルに、直接フィールドとクラスを追加してみることにしましょう。

package jp.tuyano.jasample;

import java.io.IOException;
import java.lang.reflect.*;

import javassist.*;

public class JavassistSample {

 public static void main(String[] args) {
  ClassPool pool = ClassPool.getDefault();

  try {
   CtClass cc = pool.get("jp.tuyano.jasample.TestBean");
   
   // フィールドの追加
   cc.addField(new CtField(CtClass.intType,"addfield",cc));
   
   // メソッドの追加
   String mstr = "public void addmethod(){System.out.println(\"add this method.\");}";
   cc.addMethod(CtMethod.make(mstr,cc));
   cc.writeFile();
  } catch (NotFoundException e) {
   e.printStackTrace();
  } catch (CannotCompileException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
  printTestBean();
 }

 // TestBeanのクラスとフィールドを出力する
 public static void printTestBean(){
  Class c = TestBean.class;
  System.out.println("[class]");
  System.out.println(c.getName());
  
  Method[] methods = c.getMethods();
  System.out.println("[methods]");
  for(Method m:methods){
   System.out.println(m.getName());
  }
  
  Field[] fields = c.getFields();
  System.out.println("[fields]");
  for(Field f:fields){
   System.out.println(f.getName());
  }
 }

}


これを実行すると、TestBeanのクラスファイルを書き換えて「addmethod」というメソッドと「testfield」というフィールドを追加します。追加後にTestBean内のメソッドとフィールド名を書き出していますので、ここで確認をしてみてください。これらのフィールドとメソッドが追加されているはずです。

実行するとコンソールにTestBeanクラス内のメソッドとフィールドが書き出される。


では、簡単な流れを説明しておきましょう。実際に操作を行なっているのはmainメソッドの部分になります。

ClassPool pool = ClassPool.getDefault();


まず、ClassPoolを取得します。これは、ClassPool.getDefaultでデフォルトのClassPoolが得られますので、通常はこれを使います。

CtClass cc = pool.get("jp.tuyano.jasample.TestBean");


続いて、TestBeanのCtClassを取得します。これはClassPoolのgetメソッドを使います。ここで取り出すクラス名を引数として渡せば、そのクラスのCtClassインスタンスが得られます。このとき、完全修飾名でクラスを指定するようにしておきましょう。

cc.addField(new CtField(CtClass.intType,"addfield",cc));


CtClassが得られたら、クラスを修正に進みます。最初にフィールドを追加します。フィールドは、CtFieldインスタンスとして扱われます。これは、new CtFieldとして作成します。引数には、フィールドの種類を示す値(CtClass内のクラスフィールドを使って指定します)、フィールド名、組み込み先のCtClassをそれぞれ渡します。

String mstr = "public void addmethod(){System.out.println(\"add this method.\");}";
cc.addMethod(CtMethod.make(mstr,cc));


続いてメソッドの作成です。メソッドは、あらかじめメソッドの内容をStringとして用意しておきます。そして、CtMethodのmakeメソッドで追加をします。引数には、メソッドの内容を示すStringと組み込み先のCtClassを渡します。

cc.writeFile();


修正が終わったら、最後にCtClassのwriteFileを呼び出してクラスファイルを書き換えます。これで修正した状態にクラスファイルが変更されます。


  • 前のページへ
  • 1
  • 2
  • 3
  • 5
  • 次のページへ

あわせて読みたい

あなたにオススメ

    表示について

    カテゴリー一覧

    All Aboutサービス・メディア

    All About公式SNS
    日々の生活や仕事を楽しむための情報を毎日お届けします。
    公式SNS一覧
    © All About, Inc. All rights reserved. 掲載の記事・写真・イラストなど、すべてのコンテンツの無断複写・転載・公衆送信等を禁じます