2009年10月10日

Javaで実行時にクラスパスを追加する

会社で単体テストを実行する場合、構成管理上特殊なディレクトリ配置をとっています。そんな特殊な方法をとらなくてもと思う方もいるかもしれませんが、具体的にはお見せできないのですが、現状の方法は人の開発環境に依存せず、だれがいつでも、どこのパスにsvnからチェックアウトして実施しても実行ボタンを押すだけでテストを実行させることが出来ます。これにより、初心者や新規参画者がテストを始めるまでの時間がこれまでかかっていたのですが、環境の調整を意識しなくてもテストができるため、保守効率が高くなっています。
ついでに言えば、テストプロジェクトにテスト実行用のデータを単体テスト用に配置することも無く、実行前に単体テストに必要な情報を事前にコピーしてきて利用するようになっています。
これによって、単体テスト用の設定ファイルとリリース用の設定ファイルに差異が出てしまうという事態を避けています。
データを一元管理し、正しいデータの取得はここだけを見ればよい、他は捨てても良いとしています。

これは私が考える理想の単体〜総合テストを実現する上での、まずは第一歩のようなところであります。今は仕事をやりながら、その理想のテスト方式を少しずつ導入しているところです。
(さすがに一気に変えると反発もありメリットを想像できないみたいなので、少しずつ導入しメリットを体感させて、より良くしている最中です。)

そんな中で、テスト実行時にテストプログラムが、動的にクラスパスを変更できるほうが環境依存しないケースがあることに気づきました。
ですが、Javaでそんなことできるのかしらと思いましたが、調べてみるとやはりpublicな方法はないようです。

やるとすると、以下のようにリフレクションからprivateメソッドを呼び出し、直接クラスパスをリストに追加させる方式しかないようです。

/**
* クラスパスを現在のシステムクラスローダに追加する
*
* @param classPath 追加したいクラスパス
* @throws Exception システム例外
*/
public static void addClassPathToClassLoader(File classPath)
throws Exception {

addClassPathToClassLoader((URLClassLoader) ClassLoader.getSystemClassLoader(), classPath);
}

/**
* クラスパスを指定したクラスローダに追加する
*
* @param classLoader クラスローダ
* @param classPath 追加したいクラスパス
* @throws Exception システム例外
*/
public static void addClassPathToClassLoader(URLClassLoader classLoader, File classPath)
throws Exception {

Class classClassLoader = URLClassLoader.class;

Method methodAddUrl = classClassLoader.getDeclaredMethod("addURL", URL.class);

methodAddUrl.setAccessible(true);
methodAddUrl.invoke(classLoader, classPath.toURI().toURL());
}

これを使う場合は、JREがシステムのクラスローダにURLClassLoaderを継承したクラスローダを利用していることが前提となりますのでご注意ください。
もし、ClassCastExceptionがスローされる場合は、別の方法を探すことをおすすめします。

使い方は以下のような感じになると思います。

addClassPathToClassLoader(new File("〜.jar"));

今即攻で覚えている範囲でテキストエディタで書いたのみのため、コンパイルもしていません。会社で使っているコードとも少し違って、シンプルになっています。
もしエラーがありましたら、気づいたら修正しますが、独力で修正しご利用ください。
posted by Kiruahさん at 15:18| Comment(0) | TrackBack(0) | ノウハウ
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス: [必須入力]

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/32814774
※ブログオーナーが承認したトラックバックのみ表示されます。
※言及リンクのないトラックバックは受信されません。

この記事へのトラックバック