ステップアップ--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はデフォルトで「親委任ロードチェーン」構造を採用しています. クラス図では、BootstrapClassLoaderは単独のjavaクラスですが、実はここではjavaクラスと呼ぶべきではありません.なぜならjavaでは全く実現されていないからです.jvmが起動すると、javaプラットフォームのコアライブラリを担当するように構築されます.
カスタムクラスローダでクラスをロードするには
classloader-load-class
ClassLoaderクラスのロードロジック分析.以下のロジックはBootstrapClassLoader以外のクラスローダロードプロセスです.
スレッドコンテキストクラスローダ
JAvaのデフォルトのスレッドコンテキストクラスローダはシステムクラスローダ(AppClassLoader)です.
上記のコードは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クラスローダにおける名前空間が一意であり,互いに干渉しないことを実証した.すなわち、一般的には、同じクラスに関連付けられた他のクラスが、現在のクラスのクラスローダによってロードされることを保証します.
上の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クラスを作成しようとしたときに失敗したら、この例外を投げ出す
JAva classLoaderアーキテクチャ使用の詳細
jvm classLoader architecture:
クラス・ローダのプロパティ:
各ClassLoaderは、同じ名前空間に同じ名前のクラスが2つも現れない独自の名前空間を維持しています.Javaセキュリティ砂箱モデルの最上位レベルのクラスローダセキュリティメカニズムを実現するために、javaはデフォルトで「親委任ロードチェーン」構造を採用しています. クラス図では、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)を防止することに注意してください.
なぜこのような親依頼モードを使うのでしょうか.
JAvaがclassを動的にロードする2つの方法:
クラスを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クラスを作成しようとしたときに失敗したら、この例外を投げ出す