ステップアップ--javaベース(3)--java.lang.ClassLoaderクラスの使い方

6690 ワード

原文出典:http://www.zuidaima.com/share/1774052029516800.htm オリジナルを尊重
JAva classLoaderアーキテクチャ使用の詳細
jvm classLoader architecture:
  • 1.Bootstrap ClassLoader/起動クラスローダは主にjdk_を担当するhome/libディレクトリのコアapiまたは-Xbootclasspathオプションで指定したjarパッケージワーク.
  • 2.Extension ClassLoader/拡張クラスローダは主にjdk_を担当するhome/lib/extディレクトリのjarパッケージまたは-Djava.ext.dirsディレクトリのjarパッケージの作業を指定します.
  • 3.System ClassLoader/システムクラスローダは主にjava-classpath/-Djava.class.pathが指すディレクトリの下のクラスとjarのパッケージを担当しています.
  • 4.User Custom ClassLoader/ユーザカスタムクラスローダ(java.lang.ClassLoaderのサブクラス)プログラム実行中にjava.lang.ClassLoaderのサブクラスを介してclassファイルを動的にロードし、java動的リアルタイムクラス読み込み特性を体現する.

  • クラス・ローダのプロパティ:
    各ClassLoaderは、同じ名前空間に同じ名前のクラスが2つも現れない独自の名前空間を維持しています.Javaセキュリティ砂箱モデルの最上位レベルのクラスローダセキュリティメカニズムを実現するために、javaはデフォルトで「親委任ロードチェーン」構造を採用しています.进阶--java基础(3)--java.lang.ClassLoader类的用法_第1张图片 进阶--java基础(3)--java.lang.ClassLoader类的用法_第2张图片クラス図では、BootstrapClassLoaderは単独のjavaクラスですが、実はここではjavaクラスと呼ぶべきではありません.なぜならjavaでは全く実現されていないからです.jvmが起動すると、javaプラットフォームのコアライブラリを担当するように構築されます.
    カスタムクラスローダでクラスをロードするには
    classloader-load-class
    ClassLoaderクラスのロードロジック分析.以下のロジックはBootstrapClassLoader以外のクラスローダロードプロセスです.
    //            
    Class c = findLoadedClass(name);  
    if (c == null ) {  
         //          
         try {  
             if (parent != null ) {  
                 //           ,          
                 c = parent.loadClass(name, false );  
             } else {  
                 //          ,             
                 c = findBootstrapClass0(name);  
             }  
         } catch (ClassNotFoundException e) {  
             //                  ,          
             //   ,    findClass  ,       
             c = findClass(name);  
         }  
    }  

    スレッドコンテキストクラスローダ
    JAvaのデフォルトのスレッドコンテキストクラスローダはシステムクラスローダ(AppClassLoader)です.
    // Now create the class loader to use to launch the application  
    try {  
        loader = AppClassLoader.getAppClassLoader(extcl);  
    } catch (IOException e) {  
        throw new InternalError(  
    "Could not create application class loader" );  
    }   
     // Also set the context class loader for the primordial thread. 
    Thread.currentThread().setContextClassLoader(loader);  

    上記のコードはsun.misc.Launchの無パラメトリック構造関数Launch()から抜粋されています.
    スレッドコンテキストクラスローダを使用すると、実行スレッドでは、親委任ロードチェーンモードを捨てて、スレッドコンテキスト内のクラスローダを使用してクラスをロードすることができます.典型的な例は、スレッドコンテキストによって第三者ライブラリjndiをロードすることで実現され、親委任に依存しません.java appサーバ(jboss,tomcat.)の大部分もcontextClassLoaderを使用してwebサービスを処理します.hotswapの特性を採用するフレームワークもあり、seasar(full stack framework in japenese)のようなスレッドコンテキストクラスローダも使用する.
    スレッドコンテキストは、一般的なアプリケーションが親委任モードに背くことができないという問題を根本的に解決し、javaクラスのロードシステムをより柔軟にする.
    マルチコア時代が到来するにつれて、マルチスレッド開発はますますプログラマーの実際の符号化過程に入ると信じられている.そのため、インフラストラクチャを作成する際に、スレッドコンテキストを使用してクラスをロードすることは、良い選択であるべきである.
    もちろん、良いものにはメリットとデメリットがあります.スレッドコンテキストを使用してクラスをロードする場合も、通信が必要な複数のスレッド間のクラスローダが同じであることを保証し、異なるクラスローダによるタイプ変換異常(ClassCastException)を防止することに注意してください.
    なぜこのような親依頼モードを使うのでしょうか.
  • 1.これにより、重複ロードを回避することができるので、親がクラスをロードした場合、サブClassLoaderを再ロードする必要はありません.
  • .セキュリティ要因を考慮して、このような依頼モードを使用しない場合、javaコアapiで定義されているタイプをいつでもカスタムStringで動的に置き換えることができ、非常に大きなセキュリティ上の危険性がありますが、両親が依頼する方法では、Stringが起動時にロードされているため、このような状況を回避することができます.したがって、ユーザーカスタムクラスは、カスタムClassLoaderをロードできません.

  • JAvaがclassを動的にロードする2つの方法:
  • 1.implicit暗黙的、すなわちインスタンス化してロードする特性を利用してclass
  • を動的にロードする.
  • 2.explicit明示方式、また2つの方式に分けます:
  • java.lang.ClassのforName()メソッド
  • java.lang.ClassLoaderのloadClass()メソッド

  • クラスをClass.forNameでロード
    Class.forNameは、呼び出し元のクラスローダを使用してクラスをロードします.この特性はjavaクラスローダにおける名前空間が一意であり,互いに干渉しないことを実証した.すなわち、一般的には、同じクラスに関連付けられた他のクラスが、現在のクラスのクラスローダによってロードされることを保証します.
    public static Class forName(String className)  
         throws ClassNotFoundException {  
         return forName0(className, true , ClassLoader.getCallerClassLoader());  
    }   
    
    /** Called after security checks have been made. */  
    private static native Class forName0(String name, boolean initialize,  
    ClassLoader loader)  
         throws ClassNotFoundException;  

    上のClassLoader.getCallerClassLoaderは、現在のforNameメソッドを呼び出すクラスを取得するクラスローダです.
    staticブロックはいつ実行されますか?
    呼び出しforName(String)がclassにロードされると、ClassLoader.loadClassが呼び出されても実行されません.forName(String,false,ClassLoader)が呼び出されても実行されません.Classがロードされてもstaticブロックが実行されない場合は、最初のインスタンス化時に実行されます.たとえばnew,Class.newInstance()操作
    staticブロックは1回のみ実行されます
    各javaクラスはどのclassLoaderによってロードされますか?
    JAvaクラスは、インスタンス.getClass.getClassLoader()によってインタフェースがAppClassLoader(System ClassLoader、ClassLoader.getSystemClassLoader()によってインスタンスが得られる)によってClassLoaderクラスがbootstrap loaderによってロードされることを知ることができる
    NoClassDefFoundErrorとClassNotFoundException
    NoClassDefFoundError:javaソースファイルが.classファイルにコンパイルされているが、ClassLoaderが実行中にパスloadのクラスを検索している間に.classファイルが見つからなかった場合、このエラーを報告するClassNotFoundException:String変数でClassクラスを作成しようとしたときに失敗したら、この例外を投げ出す