回転:jvm classloader

5735 ワード

回転:jvm classloader


作者:白菜发表时间:September 7,2010分类:JAVA
1.簡単な実験から始めます.
(1)Eclipseの下に簡単なJava projectを建てて、簡単なプログラムを書いて、以下のようにします:
  • package com.javaeye.loader;  
  •   
  • public class URLClassLoaderTest {  
  •     public void show() {  
  •         System.out.println("I am running...");  
  •     }  
  • }  
  • package com.javaeye.loader;public class URLClassLoaderTest {	public void show() {		System.out.println("I am running...");	}}

    (2)プロジェクト対応bin/com/javaeye/loaderの下にURLClassLoaderTestを見つける.classファイル、このファイルを保存し、プロジェクト全体を削除します.
    (3)ディスクのどこにでもフォルダcomを作成し、comにjavaeyeを作成し、javaeyeにloaderを作成し、私はCディスクjavaディレクトリの下に構築し、作成が完了したら(2)に保存するURLClassLoaderTest.classファイルをコピーし、(4)非ローカルApacheサーバ上の任意の場所にフォルダcomを作成し、comにjavaeyeを作成し、javaeyeにloaderフォルダを作成し、完了後(2)に保存するURLClassLoaderTest.classファイルはその中にコピーして、私の非ローカルコンピュータIPは192.168.66.250で、システムはLinux Redhatで、創立が完成した後に私達はアクセスして(5)両端のテストコードを与えることができます:
  •                @Test  
  • public void testInWeb() throws Exception{  
  •     URL[] urls = new URL[]{new URL("http://192.168.66.250/root/java/")};  
  •     URLClassLoader loader = new URLClassLoader(urls);  
  •     Class clas = loader.loadClass("com.javaeye.loader.URLClassLoaderTest");  
  •     Method m = clas.getMethods()[0];  
  •     Object o = clas.newInstance();  
  •     m.invoke(o);  
  • }  
  • @Test  
  • public void testInFileSystem() throws Exception{  
  •     URL[] urls = new URL[]{new URL("file:/C:/java/")};  
  •     URLClassLoader loader = new URLClassLoader(urls);  
  •     Class clas = loader.loadClass("com.javaeye.loader.URLClassLoaderTest");  
  •     Method m = clas.getMethods()[0];  
  •     Object o = clas.newInstance();  
  •     m.invoke(o);  
  • }  
  •                 @Test	public void testInWeb() throws Exception{		URL[] urls = new URL[]{new URL("http://192.168.66.250/root/java/")};		URLClassLoader loader = new URLClassLoader(urls);		Class clas = loader.loadClass("com.javaeye.loader.URLClassLoaderTest");		Method m = clas.getMethods()[0];		Object o = clas.newInstance();		m.invoke(o);	}	@Test	public void testInFileSystem() throws Exception{		URL[] urls = new URL[]{new URL("file:/C:/java/")};		URLClassLoader loader = new URLClassLoader(urls);		Class clas = loader.loadClass("com.javaeye.loader.URLClassLoaderTest");		Method m = clas.getMethods()[0];		Object o = clas.newInstance();		m.invoke(o);	}

    両端のコードをそれぞれ実行し、出力結果は次のとおりです.
    Javaコード
  • I am running...  
  • I am running...

    分析:
    なぜ上記の運転結果が現れるのかは明らかにcomのためである.learn.loader.URLClassLoaderTestオブジェクトはメモリにロードされ、このオブジェクトのshowメソッドが実行される.
    考え:
    Java言語は、Java仮想マシン(JVM)上で実行されるため、Javaでコンパイルされているプログラムがプラットフォームから独立した特殊なフォーマットであり、実行されているマシンに依存しないため、異なります.このフォーマットは、従来の実行可能プログラムフォーマットとは大きく異なる.CまたはC++で作成されたプログラムとは異なり、Javaプログラムは実行可能なファイルではなく、多くの独立したクラスファイルから構成され、各ファイルはJavaクラスに対応しています.また、これらのクラスファイルは、すぐにすべてメモリにロードされるのではなく、プログラムの必要に応じてメモリにロードされます.ClassLoaderは、JVMでクラスをメモリにロードするツールです.
     
    2.jvm classLoader architecture
    同じ例のコードを示します.
  • public void testClassLoader2() throws Exception{  
  •         URL[] urls = new URL[]{new URL("http://192.168.66.250/root/java/")};  
  •         URLClassLoader loader = new URLClassLoader(urls);  
  •         System.out.println(loader.getClass());  
  •         System.out.println(loader.getParent().getClass());  
  •         System.out.println(loader.getParent().getParent().getClass());  
  •         System.out.println(loader.getParent().getParent().getParent());  
  •     }  
  • public void testClassLoader2() throws Exception{		URL[] urls = new URL[]{new URL("http://192.168.66.250/root/java/")};		URLClassLoader loader = new URLClassLoader(urls);		System.out.println(loader.getClass());		System.out.println(loader.getParent().getClass());		System.out.println(loader.getParent().getParent().getClass());		System.out.println(loader.getParent().getParent().getParent());	}

     
    実行結果は次のとおりです.
    Javaコード
  • class java.net.URLClassLoader  
  • class sun.misc.Launcher$AppClassLoader  
  • class sun.misc.Launcher$ExtClassLoader  
  • null  
  • class java.net.URLClassLoaderclass sun.misc.Launcher$AppClassLoaderclass sun.misc.Launcher$ExtClassLoadernull

     
    この実行結果を説明するには、jvm classloader構造を以下の図に示す必要があります.
    図に示すように、javaセキュリティ砂箱モデルの最上位レベルのクラスローダセキュリティメカニズムを実現するために、javaはデフォルトで「親委任ロードチェーン」構造を採用しており、図では4層に分かれている.私たちの上の運行結果と一つ一つ対応しています.
    最下層:User Custom ClassLoader/ユーザカスタムクラスローダ(java.lang.ClassLoaderのサブクラス)は、プログラムの実行中にjavaを通過する.lang.ClassLoaderのサブクラスはclassファイルを動的にロードし、javaの動的リアルタイムクラス読み込み特性を体現する.明らかにjavanet.URLClassLoaderはこの層に属する.
    AppClassLoader層:System ClassLoader/システムクラスローダ、主にjava-classpath/-Djavaを担当する.class.pathが指すディレクトリの下のクラスとjarパッケージは作業中です.java.lang.ClassLoader.getSystemClassLoader()は、上記sunを得ることができる.misc.Launcher$AppClassLoaderはこのレイヤに属します.
    ExtClassloaderレイヤ:Extension ClassLoader/拡張クラスローダ、主にjdk_を担当home/lib/extディレクトリのjarパッケージまたは-Djava.ext.dirs指定ディレクトリのjarパッケージ作業、sun.misc.Launcher$ExtClassLoaderはこの層に属する.
    最上位:Bootstrap ClassLoader/起動クラスローダ、主にjdk_を担当home/libディレクトリのコアapiまたは-Xbootclasspathオプションで指定したjarパッケージワークは、なぜこのレイヤの出力がnullに対応するのですか?BootstrapはC++で書かれているので、Javaでは見えませんnullです.次から:http://www.javaeye.com/topic/753834