Java ClassLoaderとは何ですか?


174

いくつかの簡単な文で、Java ClassLoaderとは何ですか、いつ使用され、なぜですか?

OK、私はwikiの記事を読みました。ClassLoaderはクラスをロードします。OK。したがって、jarファイルを含めてインポートすると、ClassLoaderがその役割を果たします。

なぜこのClassLoaderに悩む必要があるのですか?私はそれを使用したことがなく、それが存在することを知りませんでした。

問題は、なぜClassLoaderクラスが存在するのですか?また、実際にどのように使用しますか?(場合によっては存在します。)


あなたが理解していない特定の部分を指すことによって、あなたの質問、例えばを絞り込む場合は、それはなど、とあなたがしているお馴染みのいくつかの他の言語にどのように関連するか、より良い結果を得るでしょう
JRL

75
これは、概念を説明するためにいくつかの簡単な文を検索している誰かの観点から見ると、完全に合理的な質問です
oxbow_lakes

このビデオは興味深いかもしれません:あなたは本当にクラスローダーを取得しますか?
asmaier 2013年

回答:


231

この素敵なチュートリアルからSunのからの:

動機

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への最近の変更から明らかです。

JDK 1.2以降、JVMに組み込まれているブートストラップクラスローダーが、Javaランタイムのクラスのロードを担当しています。このクラスローダーは、ブートクラスパスにあるクラスのみをロードします。これらは信頼できるクラスであるため、信頼できないクラスの場合と同様に検証プロセスは実行されません。ブートストラップクラスローダーに加えて、JVMには、標準の拡張APIからクラスをロードする拡張クラスローダーと、一般的なクラスパスおよびアプリケーションクラスからクラスをロードするシステムクラスローダーがあります。

複数のクラスローダーがあるため、それらはルートがブートストラップクラスローダーであるツリーで表されます。各クラスローダーには、その親クラスローダーへの参照があります。クラスローダーは、クラスをロードするように要求されると、アイテム自体をロードする前に、その親クラスローダーに問い合わせます。次に、親はその親に相談します。したがって、現在のクラスローダーが関与するのは、すべての祖先クラスローダーがクラスを見つけられない場合だけです。つまり、委任モデルが使用されます。

java.lang.ClassLoaderクラス

java.lang.ClassLoaderJVMが動的にロードクラスでの方法を拡張する必要があるアプリケーションによってサブクラス化することができる抽象クラスです。java.lang.ClassLoader(およびそのサブクラス)のコンストラクターを使用すると、新しいクラスローダーをインスタンス化するときに親を指定できます。明示的に親を指定しない場合、仮想マシンのシステムクラスローダーがデフォルトの親として割り当てられます。つまり、ClassLoaderクラスは委任モデルを使用してクラスとリソースを検索します。したがって、ClassLoaderの各インスタンスには親クラスローダーが関連付けられているため、クラスまたはリソースを検索するように要求されると、クラスまたはリソース自体を検索する前に、タスクは親クラスローダーに委任されます。loadClass()ClassLoader のメソッドは、クラスをロードするために呼び出されると、次のタスクを順番に実行します。

クラスがすでにロードされている場合は、それを返します。それ以外の場合は、新しいクラスの検索を親クラスローダーに委任します。親クラスローダーがクラスを見つけられない場合loadClass()は、メソッドfindClass()を呼び出してクラスを見つけてロードします。このfinalClass()メソッドは、親クラスローダーによってクラスが見つからなかった場合、現在のクラスローダーでクラスを検索します。


オリジナルの記事には、独自のネットワーククラスローダーを実装する方法も記載されており、理由(および方法)に関する質問に答えています。APIドキュメントもご覧ください。


47

ほとんどのJava開発者は、クラスローダーを明示的に使用する必要は決してありません(JARにバンドルされている場合でも機能するようにリソースをロードする場合を除く)。

ClassLoadersは、大規模なシステムやサーバーアプリケーションで次のようなことを行うために使用されます。

  • システムをモジュール化し、実行時にモジュールをロード、アンロード、更新する
  • 異なるバージョンのAPIライブラリ(XMLパーサーなど)を並行して使用する
  • 同じJVM内で実行されている異なるアプリケーションを分離する(たとえば、静的変数を介して相互に干渉しないことを保証する)

29

問題は、「なぜこのClassLoaderクラスが存在するのかわからないのか」ということです。

まあ、ほとんどの場合、問題が発生した場合は修正できます:-)。

確かに、アプリケーションを作成し、JARにコンパイルし、さらにいくつかの追加のライブラリJARを含める限り、クラスローダーについて知る必要はなく、機能します。

それでも、舞台裏で何が起こっているかをよりよく理解するには、クラスローダーとクラスローディングについて少し知っておくと役に立ちます。例として、「静的初期化子」はクラスがロードされるときに実行されるため、いつ実行されるかを理解するには、クラスローダーがロードするタイミングを決定する方法を知る必要があります。

また、実際にどのように使用しますか?

単純なケースでは、それらは必要ありません。ただし、コードを実行時に明示的に制御して実行時に動的にロードする必要がある場合(ネットワーク経由のロード、コンパイル時に使用できないプラグインのロードなど)は、さらに多くの操作が必要になる場合があります。次に、たとえば独自のクラスローダーを記述できます。リンクについては、他の回答を参照してください。


14

ClassLoaderin Javaは、Javaでクラスファイルをロードするために使用されるクラスです。Javaコードはjavacコンパイラによってクラスファイルにコンパイルされ、JVMはクラスファイルに記述されたバイトコードを実行することによってJavaプログラムを実行します。

ClassLoaderは、ファイルシステム、ネットワーク、またはその他のソースからクラスファイルをロードします。Javaで使用されるデフォルトのクラスローダーは3つあり、ブートストラップ拡張機能システムまたはアプリケーションのクラスローダーです。

ClassLoader


ClassLoaderの仕組み

## ClassLoaderとJVMの相互作用 ここに画像の説明を入力してください

もっと@ imgrumweb.com


6

クラスローダーはJVMの機能コンポーネントであり、「。class」ファイルから、またはネットワークを介してヒープのメソッド領域にクラスデータをロードします。

JVMの不可欠な部分のように見えますが、エンドJavaユーザーとしてなぜ私は心配する必要がありますか?理由は次のとおりです。

各クラスローダーには独自の名前空間があり、特定のクラスローダーによって呼び出されたクラスはその名前空間に入ります。

2つの異なるクラスローダーによって呼び出されたクラスは相互に可視性がないため、セキュリティが強化されます。

クラスローダーの親子委任メカニズムにより、Java APIクラスが不正なコードによってハッキングされることはありません。

詳細はこちら


1

クラスローダーは階層的です。クラスは、JVMですでに実行されているクラスで名前によって参照されるため、JVMに導入されます。

最初のクラスはどのように読み込まれましたか?
一番最初のクラスは、static main()、クラスで宣言されているメソッドを使用してされます。その後ロードされるすべてのクラスは、すでにロードされて実行されているクラスによってロードされます。

クラスローダーは名前空間を作成します。すべてのJVMには、原始(またはブートストラップ)クラスローダーと呼ばれる、JVM内に埋め込まれたクラスローダーが少なくとも1つ含まれています。それは1つのことであり、非原始的なクラスローダーを見ていきます。JVMにはフックがあり、ユーザー定義のクラスローダーを原始的なクラスローダーの代わりに使用できます。以下は、JVMによって作成されたクラスローダーです。

ブートストラップ(原始) このクラスローダーは再ロードできません。JDK内部クラス、java。*パッケージをロードします(通常はrt.jarおよびi18n.jarをロードします)。Extesionsこのクラスローダーは再ロードできません。JDK拡張ディレクトリ(通常はJREのlib / ext)からjarファイルをロードします。システムこのクラスローダーは再ロードできません。システムクラスパスからクラスをロードします。

http://www.sbalasani.com/2015/01/java-class-loaders.html


1

ClassLoaderクラスが存在する理由を尋ねると、その理由は非常に単純です。これは、実行時にクラスファイル見つけてロードする責任があるクラスです

詳しく説明しましょう。

JVMでは、すべてのクラスはのインスタンスによってロードされますjava.lang.ClassLoader。通常のJavaプログラム起動java <classname>コマンドによって新しいJVMが起動されるときはいつでも、最初のステップは、java.lang.Objectや他のランタイムクラス(rt.jar)などの適切な動作に必要なすべてのキークラスをメモリにロードすることです。

現在、ClassLoaderには3つの部分があります。

  • BootstrapClassLoaderメモリ内のこれらのクラスをロードする、すなわち、これらのクラスを利用可能にする責任があります。

  • 次のタスクは、アプリケーションが適切に機能するように、外部ライブラリ/ JARをメモリにロードすることです。ExtClassLoaderこの作業を担当しています。このクラスローダーは、java.ext.dirsパスで言及されているすべての.jarファイルをロードします。

  • 3番目で重要なクラスローダーはAppClassLoaderです。アプリケーションクラスローダーは、java.class.pathシステムプロパティに記述されているクラスファイルのロードを担当します。

また、デフォルトのClassLoader実装をオーバーライドして、便利で興味深い方法でJVMをカスタマイズし、クラスファイルをシステムに取り込む方法を完全に再定義できるようにすることも重要です。

ここに画像の説明を入力してください

Java Class Loaderの詳細については、こちらをご覧ください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.