[解決済み] Java ClassLoaderとは何ですか?
質問
Java ClassLoaderとは何か、どのような場合に使用され、なぜ使用されるのか、簡単な文章で説明してください。
OK、wikiの記事を読みました。ClassLoaderはクラスをロードします。OKです。jarファイルをインクルードしてインポートすれば、ClassLoaderが仕事をするわけだ。
なぜわざわざこのClassLoaderを使う必要があるのでしょうか?使ったこともないし、存在も知らなかった。
問題は、なぜClassLoaderクラスが存在するのか、ということです。そしてまた、実際にどのように使うのか?(ケースは存在しますよね)。
どのように解決するのか?
この素敵な作品から引用 チュートリアル を紹介しました。
モチベーション
CやC++などの静的コンパイルされたプログラミング言語で書かれたアプリケーションは、マシン固有のネイティブな命令にコンパイルされ、実行ファイルとして保存される。このコードを実行可能なネイティブコードに結合するプロセスをリンクと呼び、別々にコンパイルされたコードを共有ライブラリのコードと結合して実行可能なアプリケーションを作成します。これは、Javaのような動的コンパイルされたプログラミング言語では異なります。Javaでは、Javaコンパイラが生成した.classファイルは、Java仮想マシン(JVM)にロードされるまでそのままの形で残ります--言い換えれば、リンク処理は実行時にJVMによって実行されます。クラスは、「必要に応じて」JVMにロードされる。そして、ロードされたクラスが他のクラスに依存している場合、そのクラスも同様にロードされます。
Javaアプリケーションを起動すると、最初に実行されるクラス(またはアプリケーションへのエントリポイント)は、main()と呼ばれるpublic static voidメソッドを持つものです。このクラスは通常、他のクラスへの参照を持っており、参照されているクラスをロードする試みはすべてクラスローダーによって行われます。
この再帰的クラスローディングと一般的なクラスローディングの考え方を理解するために、次のような簡単なクラスを考えてみましょう。
public class HelloApp {
public static void main(String argv[]) {
System.out.println("Aloha! Hello and Bye");
}
}
このクラスを -verbose:class コマンドラインオプションを指定して実行し、どのクラスが読み込まれているかを表示させると、次のような出力が得られます。リストが長すぎてここに表示できないので、これは単なる部分的な出力であることに注意してください。
prmpt>java -verbose:class HelloApp
[Opened C:\Program Files\Java\jre1.5.0\lib\rt.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jsse.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jce.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\charsets.jar]
[Loaded java.lang.Object from shared objects file]
[Loaded java.io.Serializable from shared objects file]
[Loaded java.lang.Comparable from shared objects file]
[Loaded java.lang.CharSequence from shared objects file]
[Loaded java.lang.String from shared objects file]
[Loaded java.lang.reflect.GenericDeclaration from shared objects file]
[Loaded java.lang.reflect.Type from shared objects file]
[Loaded java.lang.reflect.AnnotatedElement from shared objects file]
[Loaded java.lang.Class from shared objects file]
[Loaded java.lang.Cloneable from shared objects file]
[Loaded java.lang.ClassLoader from shared objects file]
[Loaded java.lang.System from shared objects file]
[Loaded java.lang.Throwable from shared objects file]
.
.
.
[Loaded java.security.BasicPermissionCollection from shared objects file]
[Loaded java.security.Principal from shared objects file]
[Loaded java.security.cert.Certificate from shared objects file]
[Loaded HelloApp from file:/C:/classes/]
Aloha! Hello and Bye
[Loaded java.lang.Shutdown from shared objects file]
[Loaded java.lang.Shutdown$Lock from shared objects file]
ご覧のように、アプリケーションクラス(HelloApp)が必要とするJavaランタイムクラスが最初にロードされます。
Java 2 プラットフォームのクラス・ローダー
プログラミング言語Javaは、アプリケーション開発者の生活を日々快適にするために進化を続けています。これは、基本的なメカニズムの実装の詳細ではなく、ビジネスロジックに集中できるようにすることで、生活を簡素化するAPIを提供することで実現しています。このことは、Javaプラットフォームの成熟度を反映するために、最近J2SE 1.5がJ2SE 5.0に変更されたことからも明らかです。
JDK1.2以降では、JVMに組み込まれたブートストラップ・クラス・ローダーが、Javaランタイムのクラスの読み込みを担当する。このクラスローダーは、ブートクラスパスにあるクラスのみをロードし、これらは信頼できるクラスであるため、信頼できないクラスに対するような検証処理は行われない。ブートストラップ・クラス・ローダーの他に、JVMは標準的な拡張APIからクラスをロードする責任を負う拡張クラス・ローダーと、あなたのアプリケーション・クラスと同様に一般的なクラス・パスからクラスをロードするシステム・クラス・ローダーを持っています。
クラスローダーは複数存在するため、ブートストラップ・クラスローダーをルートとするツリーで表現されます。各クラス・ローダーは、その親クラス・ローダーへの参照を持っています。クラス・ローダーは、クラスをロードするように要求されると、それ自体をロードしようとする前に、その親クラス・ローダーに問い合わせます。親は今度はその親を参照し、といった具合です。つまり、すべての祖先クラス・ローダーがクラスを見つけられなかった場合にのみ、現在のクラス・ローダーが関与することになるのです。つまり、デリゲーションモデルが使用されているのです。
java.lang.ClassLoaderクラス
を使用します。
java.lang.ClassLoader
は抽象クラスで、JVMがクラスを動的にロードする方法を拡張する必要があるアプリケーションによってサブクラス化することができます。のコンストラクタは
java.lang.ClassLoader
(およびそのサブクラス) では、新しいクラス・ローダーのインスタンスを作成するときに親を指定することができます。明示的に親を指定しない場合、仮想マシンのシステム・クラス・ローダーがデフォルトの親として割り当てられます。つまり、ClassLoader クラスは、クラスとリソースを検索するためにデリゲーション・モデルを使用します。したがって、ClassLoader の各インスタンスには関連する親クラス・ローダーがあり、クラスやリソースの検索を要求されると、クラスやリソースを自ら検索しようとする前に、そのタスクが親クラス・ローダーに委譲されるようになっています。そのため
loadClass()
メソッドは、クラスをロードするために呼び出されると、以下のタスクを順番に実行します。
クラスがすでにロードされている場合は、それを返します。
そうでない場合は、新しいクラスの検索を親クラス・ローダーに委ねます。
親クラス・ローダーがクラスを見つけられなかった場合は、次のようになります。
loadClass()
メソッドを呼び出します。
findClass()
を使用して、クラスを検索してロードします。
その際
finalClass()
メソッドは、親クラスローダーでクラスが見つからなかった場合に、 現在のクラスローダーでクラスを検索します。
元記事にはさらに、独自のネットワーク・クラス・ローダーを実装する方法も紹介されており、なぜ(どのように)かという質問に答えてくれています。また APIドキュメント .
関連
-
myeclipseでコンパイルするとAntエラーが発生する javaの例外が発生しました。
-
javaの模造品QQ WeChatのチャットルーム
-
Eclipse起動エラー:javaは起動したが、終了コード=1を返した(ネット上の様々な落とし穴)
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] JavaでNullPointerExceptionを回避する方法
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Java Mapの各エントリを効率的に反復処理するには?
-
[解決済み] Javaでメモリーリークを発生させるにはどうしたらいいですか?
-
[解決済み] Javaにおけるpublic、protected、package-private、privateの違いは何ですか?
-
[解決済み] JavaでArrayListではなくLinkedListを使用するのはいつですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
エラーが報告されました。リソースの読み込みに失敗しました:サーバーは500(内部サーバーエラー)のステータスで応答しました。
-
java の例外が発生しました java
-
この行に複数のマーカーがある - HttpServletResponseが型エラーに解決できない
-
jd-gui Java Exceptionが発生しました。
-
アクセス制限です。タイプ 'Application' は API ではありません。
-
スキャナは、タイプに解決することはできません最もルーキー初心者の質問
-
Maven Pluginの実行がライフサイクル設定の対象外であるエラーの解決
-
[解決済み] フレームワークを使用したiOSアプリがデバイス上でクラッシュ、dyld: ライブラリがロードされない、Xcode 6 Beta
-
[解決済み] JavaでNoClassDefFoundErrorが発生するのはなぜですか?
-
[解決済み] LLVMとは何ですか?