Java仮想マシンのデータ領域とオブジェクトに関する予備的な議論

Java仮想マシンのメモリ領域とメモリオーバーフロー例外

1. 実行時データ領域

プログラムカウント領域、仮想マシンスタック、ローカルメソッドスタック、Javaヒープ、メソッド領域、ランタイム定数プール

  1. プログラム カウント領域: 現在実行中のバイトコード行番号を指す小さなメモリ領域

    • 役割: 分岐ジャンプ、ループ...例外処理、スレッド回復などはすべてこの領域に依存します
    • スレッドプライベート: 各スレッドは異なる場所でコードを実行するため、この領域はスレッドプライベートです。
  2. 仮想マシンスタック: スレッド実行メソッドのメモリモデルを保存するスタック構造です. 各スタックフレームにはローカル変数テーブル、オペランドスタック、メソッドの終了アドレスなどの情報が保存されます; メソッドの実行プロセスは次のようになりますスタックをポップしてスタックにプッシュするプロセス

    • ローカル変数スロット:long、double、variable など。2 つの変数スロットを占有します。具体的な実装サイズは特定の仮想マシンによって異なります。
    • スレッドプライベート: 各スレッドは独自のメソッドスタックを維持します
    • ローカル メソッド スタック: 仮想マシン スタックに似ていますが、ローカル メソッドのモデルを保存します (マージも可能)
  3. Javaヒープ:オブジェクトインスタンスを格納する、仮想マシンが管理するメモリの最大領域(クラス情報もオブジェクトクラスのオブジェクトインスタンス)

    • GC(ガベージコレクション)メインエリア:世代理論に基づき、新世代エリア(Eden+Survivor)、旧世代エリアなどに分けることができます。

    • スレッド共有: オブジェクトはスレッド間で情報を渡すことができ、スレッドはオブジェクトを共有します (スレッドの安全性の問題に注意してください)

    • メソッド領域: 特定の情報 (型情報、定数、静的変数など) を保持するヒープ (「非ヒープ」とも呼ばれる) の論理部分。

    • 実行時定数プール: 実行時にロードされるリテラルおよびシンボリック参照を保存するメソッド領域の一部

  • ダイレクトメモリ:Java仮想マシンのメモリに属さない部分、ローカルメソッドにより直接開かれた領域、参照により直接操作できるメモリ領域
    • チャネルとバッファの I/O メソッドに基づいて、ローカル メソッドが呼び出されてローカル ヒープ メモリ空間が開かれます。その後、DirectByteBuffer によって直接操作されるメモリ領域は Java 仮想マシンのメモリ管理の一部ではありません。

2. オブジェクトの探索

オブジェクト作成プロセス (6 つのステップ)、オブジェクト メモリ レイアウト (3 つの部分)、オブジェクト アクセスの配置 (2 つのメソッド)

  • オブジェクトの作成プロセス
    1. 定数プール内のクラスへのシンボリック参照を検索します。
    2. このクラスのクラス情報がヒープにロードされているかどうかを判断し、ロードされていない場合はクラスロードを実行します(第7章:クラスメンバーの割り当てと初期化はここで完了です)
    3. メモリの割り当て (作成されたオブジェクトのメモリ空間を開く: ポインタ衝突方式、フリー リスト方式)、メモリ割り当ての同期
    4. オブジェクト インスタンスは 0 に初期化されます (すべてのオブジェクト メンバーがデフォルト値になります)。
    5. オブジェクトヘッダ情報の設定
    6. コンストラクターを実行する
  • メモリ割り当て方法: GC後のメモリ空間に応じて使用
    • ポインタ衝突方式:連続したメモリ空間において、割り当てポインタが他端に移動してメモリ空間を割り当てる
    • フリーリンクリスト方式:断片化空間において、断片化空間をリンクリストにより連続的に割り当てます(アドレス空間の割り当てが連続的である必要はありません)
  • メモリ割り当ての同期方法: 異なるスレッドがオブジェクトを作成するときにメモリ割り当てが競合する可能性があるため
    • CAS+ 失敗の再試行
    • ローカル スレッド割り当てキャッシュ: 各スレッドは最初にアドレスを割り当て、最初に独自のアドレスを使用し、十分でない場合は割り当ての競合を考慮します。
  • オブジェクトのメモリ レイアウト: オブジェクトがメモリ内にどのような形式で存在するか、各部分にコンテンツが含まれるかなど (ヘッダー + インスタンス + パディング)
    • オブジェクト ヘッダー: オブジェクト自体の実行時データ (ハッシュ コード、GC 経過時間、ロック ステータス、ロック ステータスを保持しているスレッド...)、型ポインター (クラス情報を指す) を保存します。配列オブジェクトも独自の長さ情報を保存します。
    • インスタンス データ: 独自のオブジェクトのメンバーであるか、子親クラスから継承されたメンバーであるかに関係なく、ここに記録されます。
    • パディングデータ: サイズが仕様に準拠していることを保証するための無意味なパディング
  • オブジェクトアクセスメソッド
    • ハンドル アクセス方法: ヒープ内の「比較テーブル」を使用してオブジェクトの特定の場所を記録し、変数は比較テーブル内の対応する場所を指します (オブジェクトの場所が変更されても、変数の内容は変更されません) )、追加のテーブルを維持する必要があります
    • ダイレクトポインタ方式: 変数は通過せずにオブジェクトの位置を直接指します。

3. メモリオーバーフローが発生する領域

自動回復メカニズムでは、メモリ リーク (プログラミング上の理由により一部の不要なコンテンツを回復できない) ではなく、メモリ オーバーフロー (メモリ領域が不足しているため、既存のオブジェクトを保持する必要がある) が発生します。その確率はプログラムの設計上不合理です (オープニング)。配列が大きすぎる、再帰呼び出しが多すぎるなど)

プログラムカウント領域に加えて、仮想マシンスタックとJavaヒープの両方でメモリオーバーフローが発生する可能性があります

おすすめ

転載: blog.csdn.net/caqjeryy/article/details/124001896