Java仮想マシンの詳細理解:親委任モデル


Java仮想マシンの詳細理解:親委任モデル
  • 類ローダ種類
  • 起動クラスローダ(Bootstrap ClassLoader)
  • 拡張クラスローダ
  • アプリケーションクラスローダ
  • ユーザーカスタムクラスローダ
  • 親委任モデル
  • 親委任モデル
  • とは
  • 親委任モデル動作原理
  • 親委任モデルソースコード
  • クラスローダの種類
    起動クラスローダ(Bootstrap ClassLoader)
    C++を使用した実装は、仮想マシンの一部です.他のすべてのクラスローダは、仮想マシンの外部とは独立したJava実装であり、抽象クラスjava.lang.ClassLoaderから継承されています. は、libディレクトリに格納されるか、-Xbootclasspathパラメータによって指定され、 のクラスライブラリを仮想マシンメモリにロードする責任を負います.
    拡張クラスローダ(Extension ClassLoader)sun.misc.Launcher$ExtClassLoaderによって実装され、libextディレクトリまたはjava.ext.dirsシステム変数によって指定されたパス内のすべてのクラスライブラリのロードを担当し、開発者はこのローダを直接取得することができます.
    アプリケーションクラスローダsun.misc.Launcher$AppClassLoaderによって実現され、このクラスローダはClassLoaderのgetSystemClassLoader()メソッドの戻り値であるため、一般にシステムクラスローダとも呼ばれる.
    ユーザー・クラス・パスで指定されたクラス・ライブラリのロードを担当し、開発者はこのクラス・ローダを直接使用することができます.アプリケーションが独自のクラス・ローダをカスタマイズしたことがない場合、一般的には です.
    ユーザーカスタムクラスローダ(Customized Class Loader)
    ユーザーは、クラスローダを自分で定義してクラスをロードできます.すべてのクラスローダは java.lang.ClassLoader findClass(String name) です.ユーザー定義クラス・ローダのデフォルトの親ローダは、アプリケーション・ローダです.
    親委任モデル
    親委任モデルとは
    次の図のような階層関係を親委任モデルと呼ぶ.親委任モデルは を必要とし、残りのクラスローダ を必要とする.ここでのクラスローダ間の親子関係は、継承された関係ではなく、 である.
    親委任モデルの動作原理
  • クラスローダがクラスロード要求
  • を受信
  • は、自身がロードを試みるのではなく、親ローダに
  • をロードするように委任する.
  • 各クラスローダには親クラスがあるため、
  • が週次再開する.
  • 親ローダのフィードバックがロードできない場合、子は
  • を自分でロードしようとする.
  • はまた1週間にわたって再開され、
  • 親委任モデルソースコード
    ソースコードは、java.lang.ClassLoaderloadClass()に集約される.
    protected Class<?> loadClass(String name, boolean resolve)
            throws ClassNotFoundException
    {
    	//          
        synchronized (getClassLoadingLock(name)) {
            //   ,        
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                	//           ,        
                	//   ,      
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                    	//         ,             
                    	//             
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    //          ,   ClassNotFoundException   
                    //     c == null,              
                }
    
                if (c == null) {
                    // c == null,      catch  ,            
                    //             
                    //    ,       ClassNotFoundException
                    long t1 = System.nanoTime();
                    c = findClass(name);
    
                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }