1. 1 つのコマンドが 1 つのプロセスに対応します。
Java プログラムを開始すると、つまり main メソッドを開始すると、プロセスがどれほど複雑であっても、Java 仮想マシン プロセスが開始されます。異なる JVM プロセスは相互に影響を与えません。これが、Java プログラムの入り口が 1 つだけであると言われる理由です。つまり、仮想マシンによって呼び出される main メソッドです。 2 つの主要なメソッドは 2 つの JVM プロセスに対応し、2 つの異なるクラス ローダーを開始し、実際に異なるクラスを操作します。したがって、それらは互いに影響を及ぼしません。
2. クラスのロード。
クラスを使用するとき、クラスがメモリにロードされていない場合、システムはロード、接続、初期化を通じてクラスを初期化します。
1. クラスのロード: クラスのクラス ファイルを JVM に読み込み、そのクラス オブジェクトを作成することを指します。
2. クラス接続: クラスのバイナリ データを JRE にマージすることを指します。これは 3 つの段階に分かれています。
a) 検証: ロードされたクラス ファイル データが正しいことを確認します。
b). 準備: クラスの静的変数に記憶領域を割り当て、デフォルトの初期化を実行します。
c). 解析: クラスのバイナリ データ内のシンボル参照を直接参照に置き換えます。
3. 初期化: クラスの静的変数と静的初期化ブロックを初期化します。
(注: 最終型の静的プロパティの場合、プロパティ値がコンパイル時に取得されている場合、プロパティを呼び出してもクラスは初期化されません。これは定数を使用することと同じであるためです。
ClassLoader() メソッドを使用すると、クラスがロードされるだけで、初期化されません。 )
3. クラスローダー。
クラス ローダーは、.class ファイルをメモリにロードし、対応する java.lang.Class オブジェクトを生成します。クラスが JVM にロードされると、再度ロードされることはありません。
Java では、クラスは完全修飾クラス名 (つまり、パッケージ名 + クラス名) によって識別されます。
JVM では、クラスは完全修飾クラス名とクラス ローダーによって識別されます。
JVM の実行中に、BootstrapClassLoader (ルート クラス ローダー)、ExtClassLoader (拡張クラス ローダー)、および AppClassLoader (システム クラス ローダー) という 3 つの ClassLoader が生成されます。 UML の構造は次のとおりです。
このうち、BootstrapClassLoader は、JRE のコア クラス ライブラリのロードを担当します。これは ClassLoader のサブクラスではなく、C++ で記述されているため、サブクラスの getParent() メソッドを通じて取得すると、null が返されます。返される。 BootstrapClassLoader は、rt.jar や charsets.jar などの Java コア クラス ライブラリを JRE ターゲットにロードする役割を果たします。
図からわかるように、ExtClassLoader と AppClassLoader は ClassLoader のサブクラスです。これらは API では見ることができません。rt.jar ファイル内にあります。完全修飾クラス名は次のとおりです。
sun.misc.Launcher$ExtClassLoader と sun.misc.Launcher$AppClassLoader。
このうち、ExtClassLoader は JRE 拡張ディレクトリ ext に JAR パッケージをロードする役割を担い、AppClassLoader はクラスパス パスの下にあるクラス パッケージをロードする役割を担います。
テストは次のとおりです。
次のようにコードをコピーします。
パッケージ com.stopTalking.crazy;
パブリック クラス TestClassLoader {
public static void main(String[] args) {
// 現在のスレッドのクラスローダーを取得します
ClassLoader ローダー = Thread.currentThread().getContextClassLoader();
//Systemクラスのクラスローダーを取得
ClassLoaderloader1 = System.class.getClassLoader();
//このクラスのクラスローダーloader2を取得 TestClassLoader
ClassLoaderloader2 = TestClassLoader.class.getClassLoader();
//loader2の親クラスを取得する
クラスローダーローダー3 =ローダー2.getParent();
//loader2の親クラスの親クラスを取得
クラスローダーローダー4 =ローダー3.getParent();
System.out.println(ローダー);
System.out.println(loader1);
System.out.println(loader2);
System.out.println(loader3);
System.out.println(loader4);
}
}
コンソール出力:
次のようにコードをコピーします。
//現在のスレッドクラスによって取得されるクラスローダーはAppClassLoaderです
sun.misc.Launcher$AppClassLoader@6b97fd
//System クラスはルート ローダーによってロードされ、Java からアクセスできないため、null になります
ヌル
//このクラスのクラスローダーももちろんAppClassLoaderです
sun.misc.Launcher$AppClassLoader@6b97fd
sun.misc.Launcher$ExtClassLoader@1c78e57
ヌル