[Java] Javaでのクラスの読み込みとオブジェクトの作成

JAVAクラスローディングメカニズム

Javaクラスの読み込みは、読み込み、接続(検証、準備、分析)、初期化、使用、および読み込み解除の5つのプロセスに分かれています。

  1. ロード
    ロードとは、主にバイナリバイトストリームを介して.classファイル(またはzipパッケージ)をJVMに読み込むことです。ロード段階では、JVMは3つのことを完了する必要があります
    。1)クラスローダーを介してクラスパスからXXX.classファイルを取得し、バイナリストリームの形式でメモリに読み込みます。
    2)バイトストリームで表される静的ストレージ構造をメソッド領域のランタイムデータ構造に変換する;
    3)メモリ内にこのクラスのjava.lang.Classオブジェクトを生成して、メソッド領域内のこのクラスのさまざまなデータにアクセスするエントランス。

2.1。検証
主に、ロードされたバイトストリームがJVM仕様に準拠していることを確認します。検証フェーズでは、検査アクションの次の4つのフェーズが完了します
。1)ファイル形式の検証
2)メタデータの検証(Java言語仕様に準拠しているかどうか)
3)バイトコードの検証(プログラムのセマンティクスが正当で論理的であるかどうかを確認)
4)シンボル参照の検証( (次の分析が正常に実行できることを確認してください)
2.2。準備
準備は接続フェーズの2番目のステップで、主にメソッド領域の静的変数にメモリを割り当て、デフォルトの初期値を設定します。
2.3。解決
解決は、接続フェーズの3番目のステップですこれは、仮想マシンが定数プール内のシンボル参照を直接参照に置き換えるプロセスです。

  1. 初期化初期
    化フェーズは、クラスの読み込みプロセスの最後のステップです。これは、主にプログラムの割り当てステートメントに従ってクラス変数に値をアクティブに割り当てることです。
    継承関係がある場合、親クラスが最初に初期化され、次に子クラスが初期化されるため、子クラスが作成されると、実際には2つのオブジェクトインスタンスがメモリに存在します。
    注:クラスの継承関係が長すぎる場合は、クラスの初期化のみを考慮すると、この設計は望ましくありません。理由はお分かりだと思います。
    一般に、クラスの継承関係は、最大3レベル、つまり親子孫を超えないようにすることをお勧めします。いくつかの特別なアプリケーションシナリオでは、レイヤー4が追加される場合がありますが、レイヤー4にはすでにコード設計上の欠陥があります。

  2. プログラム間の相互呼び出しを使用します。
  3. アンロードと
    は、オブジェクトを破棄することを意味します。これは通常、JVMガベージコレクターによって行われます。コードレベルでの破棄は、参照をnullに設定するだけです。

上記の全体的な概要を通過した後、Singleton2.getInstance()の実行分析を見てみましょう:
1)クラスのロード。Singleton2.getInstance()を実行すると、JVMは初めてSingletonクラスの関連情報を見つけられませんでした。したがって、Singleton.classファイルはクラスローダーを介してメモリにロードされます。
2)クラス検証。
3)授業準備は省略されます。Singleton2の静的リソースをメソッド領域に変換します。Value1、value2、およびシングルトンは、メソッド領域で最初は0、0、およびnullとして宣言されています。
4)クラス分析。省略(定数プール内のシンボル参照を直接参照に置き換えるプロセス)
5)クラスの初期化。静的プロパティの割り当てを実行します。最初の順序value1 = 5、value2 = 3、続いてプライベート静的Singleton2 singleton2 = new Singleton2( );
この操作は、コンストラクターSingleton2を実行する前に結論1に従ってオブジェクトを作成し、静的および非静的リソースリソースを実行します。しかし、value1とvalue2が初期化されているため、次の実行は非静的リソースであり、最後にSingleton2の構築メソッドです:value1 ++; value2 ++。
したがって、Singleton2は6と4になります。

実行順序を明確にすることに加えて、もう1つの重要なポイントがあります。- > 結論2:静的リソースは、クラスの初期化で一度だけ実行されます。3番目のステップと混同しないでください。

上記の結論を踏まえて、Singleton.getInstance()の実行分析を見てみましょう:
1)クラスのロード。シングルトンクラスをメモリにロードします。
2)クラス検証。
3)授業準備は省略されます。Singleton2の静的リソースをメソッド領域に変換します。
4)クラス分析。省略(定数プール内のシンボル参照を直接参照に置き換えるプロセス)
5)クラスの初期化。静的プロパティの割り当てを実行します。結論1結論2によると 、 1次のプライベート静的シングルトンシングルトン=新しいシングルトン( )は、 この演算レイヤーvalue1とvalue2の割り当てを実行しません。したがって、シングルトンオブジェクトのvalue1とvalue2は、0に基づく++演算のみです。このとき、シングルトンオブジェクトのvalue1 = 1およびvalue2 = 1です。
次に、public static int value1 = 5; public static int value2 = 3;これらの2行のコードは、実際に割り当て操作を実行します。つまり、最終結果は5と3です。
実装がpublic static int value1; public static int value2の場合、結果はどうなりますか?結果:1と1。

注:シングルトンシングルトン= new Singleton()がvalue1、value2を割り当てないのはなぜですか?静的変数の割り当ては、クラスの初期化時に一度だけ行われるためです。
プログラムがプライベート静的シングルトンシングルトン=新しいシングルトン()を実行するとき、シングルトンクラスの静的変数にはすでに値が割り当てられています。ここで、新しいSingleton()は、再帰的な内部層と同様の特別な割り当てです。外部層は既に割り当て操作であるため、内部層は静的変数の割り当て操作を自動的にフィルター処理します。ただし、非静的変数は引き続き割り当てられます。

結論3:結論2に基づいて、非静的リソースはオブジェクトの作成で初期化されます。オブジェクトが作成されるたびに、初期化が実行されます。

結論1、2、3をマスターすることは、Javaクラスでのプログラム実行の順序に基本的に精通しています。これは十分ではありません。ClassLoaderはまだ導入されていません。

クラスローダー

JVMは、次の3つのシステムクラスローダーを提供します。

  • ブートストラップClassLoader:トップレベルのクラスローダーは、JAVA_HOME \ libディレクトリまたは-Xbootclasspathパラメータで指定されたパスをロードし、仮想マシン(rt.jarなどのファイル名で識別)に認識されます。 )タイプ。
  • 拡張ClassLoader:JAVA_HOME \ lib \ extディレクトリまたはjava.ext.dirsシステム変数で指定されたパスにクラスライブラリをロードします。
  • Application ClassLoader:システムクラスローダーとも呼ばれ、getSystemClassLoader()を介して取得でき、ユーザーパス(クラスパス)にクラスライブラリをロードします。カスタムクラスローダーがない場合、これは通常、デフォルトのクラスローダーです。

オブジェクトの作成:

img

免責事項:このブログ投稿は調査ノートであり、一部のネットワークリソースを参照しています。侵害がある場合は、プライベートメッセージでお知らせください。

おすすめ

転載: blog.csdn.net/qq_42380734/article/details/105397532