Javaクラスローダーは、Javaランタイム環境の一部であり、JavaクラスをJava仮想マシンに動的にロードします 。[ 1 ] [ 2 ]通常、クラスは必要に応じてのみロードされます。仮想マシンは、プログラムの実行に必要なクラスファイルのみをロードします。[ 3 ] Javaランタイムシステムは、ファイルやファイルシステムについて知る必要はありません。これはクラスローダーに委任されているからです。
ソフトウェアライブラリとは、関連するオブジェクトコードの集合です。Java言語では、ライブラリは通常JARファイルにパッケージ化されます。ライブラリには、さまざまな種類のオブジェクトを含めることができます。JARファイルに含まれる最も重要なオブジェクトはJavaクラスです。クラスは、名前付きのコード単位と考えることができます。クラスローダーは、ライブラリの場所を特定し、その内容を読み込み、ライブラリに含まれるクラスをロードする役割を担います。このロードは通常「オンデマンド」で行われ、プログラムによってクラスが呼び出されるまで実行されません。特定の名前を持つクラスは、特定のクラスローダーによって一度だけロードできます。
各Javaクラスはクラスローダーによってロードされなければなりません。[ 4 ] [ 5 ]さらに、Javaプログラムは外部ライブラリ(つまり、プログラムの作成者以外の人物によって作成および提供されたライブラリ)を使用したり、少なくとも部分的に複数のライブラリで構成されたりする場合があります。
JVMが起動されると、3つのクラスローダーが使用されます。[ 6 ] [ 7 ] [ 3 ]
ブートストラップクラスローダーは、 (またはJava 9以降の場合は)ディレクトリにあるコアJavaライブラリ[ fn 1 ]をロードします。このクラスローダーはコアJVMの一部であり、ネイティブコードで記述されています。ブートストラップクラスローダーは、どのオブジェクトにも関連付けられていません。[ 3 ]例えば、はを返します。[ 3 ]<JAVA_HOME>/jre/lib<JAVA_HOME>/jmods>ClassLoaderStringBuilder.class.getClassLoader()null
<JAVA_HOME>/jre/lib/ext拡張機能クラスローダーは、拡張機能ディレクトリ([ 6 ]java.ext.dirsまたはシステムプロパティで指定されたその他のディレクトリ)内のコードをロードします。
システムクラスローダーは、環境変数java.class.pathにマッピングされるコードをロードします。CLASSPATH
Java クラスローダーは Java で記述されています。そのため、Java 仮想マシンの詳細を理解していなくても、カスタムクラスローダーを作成することが可能です。ブートストラップクラスローダーを除き、すべての Java クラスローダーには親クラスローダーがあります。[ 8 ]親クラスローダーは、新しいクラスローダーがインスタンス化されるとき、または仮想マシンのシステムデフォルトクラスローダーに設定されるときに定義されます。
これにより、例えば以下のようなことが可能になります。
Jakarta EE (旧称 Java EE および J2EE) アプリケーションサーバーは通常、クラスローダーのツリーによってデプロイされたWARまたはEARアーカイブからクラスをロードし、アプリケーションを他のアプリケーションから分離しますが、デプロイされたモジュール間でクラスを共有します。いわゆる「サーブレットコンテナ」は通常、複数のクラスローダーの観点から実装されます。[ 5 ] [ 10 ]
JAR ヘルは、 DLL ヘルと同様の用語で、クラスローディングプロセスが正常に動作しなくなるさまざまな状況を説明するために使用されます。[ 11 ] JAR ヘルが発生する可能性のある 3 つの方法は次のとおりです。
OSGi Allianceは、(1998年にJSR 8として)ME、SE、EE環境における現在および将来のVMのJAR地獄を解決することを目的としたモジュール性フレームワークを規定し、広く採用されています。JARマニフェストのメタデータを使用することで、JARファイル(バンドルと呼ばれる)はパッケージごとに接続されます。バンドルはパッケージのエクスポート、インポート、およびパッケージの非公開化が可能で、モジュール性とバージョン管理された依存関係管理の基本的な構成要素を提供します。
Java 9 では2017 年にJava Platform Module System が導入されました。これは、Java コードと関連リソースのコレクションの配布形式を規定しています。また、これらのコレクション (モジュール)を格納するリポジトリを規定し、それらを検出、ロード、および整合性チェックする方法を識別します。既存のJAR形式のいくつかの欠点を修正することを目的として、名前空間などの機能が含まれています。Java Platform Module System は、JRE が提供するクラスのロードのデフォルトメカニズムを使用して後方互換性のある方法で Java Runtime Environment にモジュール性を提供することを目的とした OSGi アーキテクチャとは異なる哲学に従っています。ただし、Java Platform Module System は異なるバージョンのライブラリの制御された共存機能を提供しないため、JAR 地獄の問題を完全に解決するものではありません。[ 13 ]