クラスの出自

Javaである程度の規模のプログラムを作成した場合、.classファイルを.jarファイルにアーカイブして使うことが多いと思います。Jakarta Commons等を使っている場合それらのj.jarファイルもクラスパスに置きますから、通常は複数の.jarファイル(と.jarに入れていない.classファイル)を使ってプログラムを実行します。

特にプログラムの開発中は、修正中のクラス以外は.jarのものを使うけれど修正中のクラスだけは.jarの外のものを使う、という状況が起き得ます。.javaファイルを一所懸命に修正していても、実は実行は.jarのクラスが使われてしまう、といった混乱の元になるので、あまりこうした事はやらないほうが良いのですが、やむをえない場合もあります。 そうした時に、実行中のクラスがどの.jarファイルに含まれているのかを知りたいと思うでしょう。

インスタンスの構造や機能はクラスによって決まりますが、そのクラスそのものの構造や機能を定義するクラス(メタクラス)が、Javaではjava.lang.Classというクラスとして提供されています。クラスの構造にアクセスするReflectionの機能なんかは、まさにこのClassを利用しています。このClassのオブジェクトには、そのクラスをロードしたクラスローダの情報や、そのクラスの出自の情報も入っていますので、これを使えば使用中のクラスがどのjarからやってきているのか知ることができます。

import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;

/**
 * Classに関連するユーティリティクラス。
 */
public class ClassUtil {

	/*
	 * ClassのCodeSourceのURLを返す。
	 * @param c 調査対象のClassオブジェクト。
	 * @return cのCodeSourceのURLまたはnull
	 */
	public static URL getCodeSourceURL(Class c) {
		// ClassオブジェクトのProtectionDomainを取得
		ProtectionDomain pd = c.getProtectionDomain();
		if (pd == null) {
			return null;
		}

		// そのCodeSourceを取得。
		CodeSource cs = pd.getCodeSource();
		if (cs == null) {
			return null;
		}

		// CodeSourceのLocationを返す。
		return cs.getLocation();
	}
}

このClassUtil.getCodeSourceURL()メソッドを使えば、現在実行中のプログラム内で、targetという対象のオブジェクトがあった場合、ClassUtil.getCodeSourceURL(target.getClass());を呼び出して、その戻り値を見ることで、targetオブジェクトのクラスがどこからロードされたのかを知ることができます。

ProtectionDomainやCodeSourceについてはJREのAPIのJavadocを読んでみてください。読んでもよく解らないかもしれませんが。


人材開発室 PoisonSoft