Java仮想マシンクラスローダの------クラスとクラスローダ


クラスローダはクラスのロード動作を実現するためにのみ使用されますが、Javaプログラムで果たす役割はクラスロードフェーズに限られません.いずれのクラスに対しても、ロードされたクラスローダは、Java仮想マシンでの一意性をこのクラス自体とともに確立する必要があります.この言葉はもっと一般的に表現することができます:2つのクラスが「等しい」かどうかを比較して、この2つのクラスが同じクラスのローダによってロードされている前提の下でこそ意味があります.そうしないと、この2つのクラスが同じClassファイルに由来していても、ロードされたクラスのローダが異なる限り、この2つのクラスは必ず等しくありません.
ここでいう「等しい」とは、クラスを表すClassオブジェクトのequals()メソッド、isAssignableFrom()メソッド、isInstance()メソッドの戻り結果、instanceofキーワードを用いたオブジェクトの属する関係判定などを含む.クラス・ローダの影響に気づかない場合、場合によっては迷いのある結果が発生する可能性があります.次のコードは、instanceofキーワード演算結果に及ぼす異なるタイプのローダの影響を示します.
public class ClassLoaderTest {
    public static void main(String args[])throws Exception{
		ClassLoader myLoader=new ClassLoader(){
			@Override
			public Class<?> loadClass(String name)throws ClassNotFoundException{
				try{
					String fileName=name.substring(name.lastIndexOf(".")+1)+".class";
					InputStream in=getClass().getResourceAsStream(fileName);
					if (in==null)
					{
						return super.loadClass(name);
					}
					byte[] b=new byte[in.available];
					in.read(b);
					return defineClass(name,b,0,b,length);
				} catch (IOException e) {
					throw new ClassNotFoundException(name);
				}
			}
		};

		Object obj=myLoader.loadClass("org.fenixsoft.classloading.ClassLoaderTest").newInstance();
		System.out.println(obj.getClass());
		System.out.println(obj instanceof org.fenixsoft.classloading.ClassLoaderTest);
	}

}
実行結果:
class org.fenixsoft.classloading.ClassLoaderTest
false
上のコードには単純なクラスローダが構築されています.醜いにもかかわらず、このプレゼンテーションでは十分です.同じパスの下にあるClassファイルをロードできます.このクラス・ローダを使用して、「org.fenixsoft.classloading.classLoaderTest」というクラスをロードし、このクラスのオブジェクトをインスタンス化します.2行の出力結果では、1文目からこのオブジェクトがクラスorg.fenixsoft.classloading.classLoaderTestとインスタンス化されたオブジェクトであることがわかりますが、2文目からこのオブジェクトがクラスorg.fenixsoft.classloading.classLoaderTestと所属関係タイプチェックをしている間にfalseに戻っていることがわかります.これは、仮想マシンに2つのClassLoaderTestクラスが存在しているためです.1つはシステムアプリケーションクラスのローダで、もう1つは私たちがカスタマイズしたクラスのローダでロードされています.同じClassファイルから来ていますが、依然として2つの独立したクラスで、オブジェクトが属するタイプのチェックをするとfalseになります.