[Java] Dynamic Java Compilation

ユニットテストのプロジェクトで、数種のユニットテストを一つのTest Suiteにまとめ上げるために、コンパイルに続いて、動的なコード生成をする必要がありました。普通ならTest Suiteクラスを書いて、コンパイル、実行という流れですが、この類のプロセスを自動化するにはどうしたものか、と…。
そんなときは、Java 6のjavax.tools.JavaCompilerというクラスがお役に立ちます。やり方は以下の通りです。
  1. 文字列(StringBuffer、byte array、CharSequenceなど)のJavaコードを作成します
  2. コードをコンパイルしてクラスにします
  3. コンパイルしたコードをClassLoaderでロードすると、クラスパスに登録されます
  4. 生成したクラスを実行します
JavaCompilerの通常の振る舞いは、コンパイルされたクラスをディスクに書き込むことですが、そうではなく、添付ファイルにて説明しているような、メモリ上にコンパイル済みクラスを配置する方法があります。
しかしまだるっこしい制約があります。JavaCompilerはカスタムClassLoaderを用いることができません。つまり動的コンパイルで生成されたクラスは他のクラスの動的コンパイルのために利用できないということです。
これは、例えば、ClassAクラスを作成して、ClassAクラスを拡張したClassBクラスを生成してロードした場合、ClassBクラスをコンパイルするとClassAがない、というClassNotFoundExceptionを吐く、ということです。
この問題は、ASMのようなライブラリを使ってJVMバイトコードを生成すれば回避できますが、この回避策を使うと、JavaとJVMバイトコードは全く異なる言語であるがために、デバッグがやや難しくなってしまいます。


原文はこちら。
http://blogs.oracle.com/ateamsoab2b/entry/dynamic_java_compilation

0 件のコメント:

コメントを投稿