山下寛人オフィシャルブログ

オイシックス株式会社 執行役員 システム本部長 山下寛人の公式ブログです。

Javassistでクラスを改造

try~catchをテストするにはtryブロックの

中でExceptionを発生させないといけません。

しかしExceptionを意図的に発生させるのは

難しいケースが多いです。

そこで、今後作るプログラムについては

テスト時にExceptionを発生させられるように

作るようにしようと思います。

問題は既存のプログラムです。

Exceptionを発生させるコードを組み込むと

たくさんのクラスに手を入れないといけなく

なります。

できればそれは避けたいところです。

そこで、Javassistで実行時にExceptionの

発生を組み込めないか試してみました。

以下のようなコードでできました。


組み込み対象クラス


package com.oisix.test.temp;

public class JavassistClass {
public void method() {
System.out.println("method called");
return;
}

}



組み込むクラス


package com.oisix.test.temp;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

public class Javassist {
public static void main(String args[]) throws Exception {
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("com.oisix.test.temp.JavassistClass");
CtMethod m = cc.getDeclaredMethod("method");
m.insertBefore("if(\"y\".equals(System.getProperty(\"JavassistClass\"))){throw new RuntimeException();}");
Javassist js = new Javassist();
cc.toClass(js.getClass().getClassLoader(), js.getClass()
.getProtectionDomain());
System.setProperty("JavassistClass", "y");

JavassistClass jc = new JavassistClass();
jc.method();

}

}


これくらいだったらコードを見ればだいたい

そのままわかると思います。

cc.toClass()というのはクラスローダにロードさせる

処理です。

ここでは現在のクラスローダにロードさせています。

1回クラスロードすると再読み込みはできません。

そのため最初に読み込まれる前に変換をするのが

ポイントです。