English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
第23段: JAVAソースコードのコンパイルは三つのプロセスから成り立っています:
1第22段: 、ソースコードコンパイルメカニズム。
2第21段: 、クラスロードメカニズム
3第20段: 、クラス実行メカニズム
第19段: 私たちはここでコンパイルとクラスロードの二つのメカニズムについて紹介します。
第18段: 一、ソースコードコンパイル
第17段: コードのコンパイルはJAVAソースコードコンパイラによって行われます。主にソースコードをバイトコードファイル(classファイル)にコンパイルします。バイトコードファイルの形式は主に二つの部分に分かれており、それは常量プールとメソッドのバイトコードです。
第16段: 二、クラスロード
第15段: クラスのライフサイクルは、バーチャルマシンメモリにロードされてから、メモリからアンロードされるまでです。プロセスは七つの段階に分かれており、初期化までのものはすべてクラスロードの部分に属します。
第14段: ロード----第13段: 验证----第12段: 准备----第11段: 解析-----第10段: 初始化----第9段: 使用-----第8段: 卸載
第7段: システムは、あるクラスを使用する最初のタイミングでそのクラスをロードする可能性があり、また、そのクラスをロードするためにプレロードメカニズムを用いる可能性があります。javaプログラムを実行するとき、javaバーチャルマシンプロセスが起動し、二つのjavaプログラムは二つの異なるJVMプロセスに存在し、これらのJVMはデータを共有しません。
1第6段: 、ロード段階
第5段: このプロセスのロードは、クラスロードメカニズムの一つの段階です。この二つの概念を混同しないように、この段階で実行する必要があることには:
1第4段: このクラスの完全限定名を通じて、このクラスを定義する二進位バイトストリームを取得します。
2第3段: このバイトストリームを表す静的ストレージ構造を、方法区のランタイムデータ構造に変換します。
3第2段: 這個類的Classオブジェクトをjavaヒープで生成し、これを通じて方法区に存在するデータへのアクセスを提供します。
第1段: 最初点并未指明从何处以及如何获取类的二進位字節流,因此這個區域留給開發者很大的發揮空間。這一點我在後面的類加載器中會進行介紹。
2、準備段階
この段階では、クラス変数(static修飾子が付いている変数)にメモリを割り当ててクラス変数の初期値を設定します。このメモリ割り当てはメソッドエリアで行われます。
1、ここではインスタンス変数にメモリ割り当ては行われていません。インスタンス変数はオブジェクトのインスタンス化時にオブジェクトとともにJAVAヒープに割り当てられます。
2、ここで設定される初期値は、通常データ型のゼロ値を指します。
private static int a = 3;
このクラス変数aの準備段階後の値は0で、3変数aに割り当ては初期化段階で行われます。
3、初期化段階
初期化はクラスロードメカニズムの最後のステップであり、この時点でクラス内で定義されたJAVAプログラムコードが実際に実行されます。前の準備段階では、クラス変数は一度システムが要求する初期値に設定されていますが、初期化段階では最も重要なことはクラス変数の初期化であり、特に父子クラス間の各種リソースの初期化順序が注目されます。
javaクラスでは、クラス変数に初期値を指定する方法は二種類あります:1、クラス変数を宣言する際に初期値を指定する場合;2、クラス変数に初期値を指定するための静的初期化ブロックを使用する場合。
初期化のタイミング
1)インスタンスを作成する際には、以下のものがあります:1、newキーワードを使用してインスタンスを作成する場合;2、反射でインスタンスを作成する場合;3、反序列化方法でインスタンスを作成する場合。
new Test(); Class.forName("com.mengdd.Test");
2)特定のクラスのクラスメソッド(静的メソッド)を呼び出す場合。
Test.doSomething();
3)特定のクラスまたはインターフェースのクラス変数にアクセスしたり、そのクラス変数に値を割り当てる場合。
int b=Test.a; Test.a=b;
4)特定のクラスのサブクラスを初期化する場合、そのサブクラスのすべての親クラスが初期化されます。
5)java.exeコマンドを使用して特定のメインクラスを実行する方法。
上記の方法以外でクラスを自動的に初期化する方法は、クラスへのアクセス方法すべてが、クラスの初期化を引き起こさないとされています。これをパスティブリファレンスと呼びます。
1、子クラスが親クラスの静的変数を参照すると、子クラスの初期化は引き起こされません。
public class SupClass { public static int a = 123; static { System.out.println("supclass init"); } } public class SubClass extends SupClass { static { System.out.println("subclass init"); } } public class Test { public static void main(String[] args) { System.out.println(SubClass.a); } }
実行結果:
supclass init
123
2、配列で参照クラスを定義すると、このクラスの初期化は引き起こされません
public class SupClass { public static int a = 123; static { System.out.println("supclass init"); } } public class Test { public static void main(String[] args) { SupClass[] spc = new SupClass[10]; } }
実行結果:
3、常量を参照する場合、そのクラスの初期化はトリガーされません。
public class ConstClass { public static final String A= "MIGU"; static { System.out.println("ConstCLass init"); } } public class TestMain { public static void main(String[] args) { System.out.println(ConstClass.A); } }
実行結果:
MIGU
final修飾子で特定のクラス変数を修飾すると、その値はコンパイル時に既に決まっており、常量プールに格納されています。したがって、そのクラス変数にアクセスする際には、常量プールから直接取得し、そのクラスを初期化することはありません。
初期化のステップ
1、そのクラスがまだロードされていない場合、プログラムはまずそのクラスをロードし、接続します。
2、そのクラスの直接の親クラスがまだロードされていない場合、まずその直接の親クラスを初期化します。
3、クラスに初期化文がある場合、システムはこれらの初期化文を順に実行します。
第2ステップで、直接の親クラスがさらに直接の親クラスを持っている場合、システムはこれらの3つのステップを再び繰り返してその親クラスを初期化します。これを順に続けます。JVMは最初にjava.lang.Objectクラスを初期化します。プログラムがどのクラスも使用するたびに、システムはそのクラスとすべての親クラスが初期化されることを保証します。
以上は編集者が皆さんに紹介したJAVAクラスロードメカニズム(推奨)です。皆さんに役立つことを願っています!
声明:この記事の内容はインターネットから収集され、著作権者に帰属します。インターネットユーザーが自発的に貢献し、アップロードしたものであり、このサイトは所有権を持ちません。また、人工編集は行われていません。著作権侵害が疑われる場合は、以下のメールアドレスまでご連絡ください:notice#oldtoolbag.com(メールを送信する際は、#を@に置き換えてください。)侵害を報告し、関連する証拠を提供してください。一旦確認がとれましたら、このサイトは侵害された内容をすぐに削除します。