この記事では主に、Javaランタイムデータ領域、オブジェクト作成、ガベージコレクションアルゴリズム、リサイクル戦略を含む、Javaのメモリ割り当てとリサイクルメカニズムについて説明します。
PHP中国語Webサイト講座「JAVA初級入門ビデオチュートリアル」を参考に、チュートリアルの内容を元に筆者が要約して図解しただけです。内容のこの部分は、理解と記憶を容易にするために、可能な限り図、テキスト、または表の形式で提示されます。
1. 実行時データ領域
次の図は、実行時の Java 仮想マシンのメモリ図です:
この図から、Java メモリが次のように分割されていることがわかります。 6 つの部分:
プログラム カウンター: 各スレッドには独立したプログラム カウンターがあります、 このカウンターは、現在のスレッドによって実行されるバイトコードの行番号インジケーターとして見ることができます。バイトコード インタプリタが動作すると、このカウンタの値を変更して、実行する次のバイトコード命令、分岐、ループ、ジャンプ、例外処理、およびスレッド回復などの基本的な機能はすべてこのカウンタに依存します。完了です。
Java 仮想マシン スタック: 仮想マシン スタックはスレッドに対してプライベートであり、ライフ サイクル はスレッドと同じです。仮想マシン スタックは、Java メソッド実行のメモリ モデル を記述します。各メソッドが実行されると、ローカル 変数 テーブル、オペランド スタック、ダイナミック リンク、メソッド出口などの情報を保存するためのスタック フレームが作成されます。 各メソッドの呼び出しから実行完了までの処理は、スタックフレームを仮想マシンのスタックにプッシュしてからポップアウトするまでの処理に相当します。
- ローカル メソッド スタック: 仮想マシン スタックと同様の役割を果たします。違いは、仮想マシン スタックは Java メソッドの実行を提供し、
ローカル メソッド スタックはネイティブ メソッド を提供することです。
- ヒープ:
すべてのスレッドによって共有される領域。仮想マシンの起動時に作成され、ほぼすべてのオブジェクト インスタンスがヒープ上に割り当てられます。 Java ヒープは、新世代と旧世代にさらに分割することもできます。詳しくは、Eden 空間、From Survivor 空間、To Survivor 空間があります。ただし、どのように分割しても、すべてのオブジェクト インスタンスは保存されます。さらに分割する目的は、メモリをより適切に再利用したり、メモリをより速く割り当てたりすることです。
- メソッド領域:
メソッド領域は各スレッドが共有するメモリ領域で、主に仮想マシンがロードするクラス情報、定数、静的変数、ジャストインなどのデータを格納するために使用されます。 -time コンパイルされたコード。 この領域は、Java ヒープと同様、連続メモリを必要とせず、固定または拡張可能であり、ガベージ コレクションを実装しないことも選択できます。この領域のメモリ リサイクル ターゲットは主に定数プールのリサイクルと型のアンロードのためであり、この領域ではガベージ コレクション 動作 はほとんど発生しません。
- ランタイム定数プール: ランタイム定数プールはメソッド領域の一部です。
クラスクラスのバージョン、フィールド、メソッド、インターフェースなどの説明情報に加えて、コンパイル中に生成されるさまざまなリテラルやシンボル参照を保存するために使用される定数プールもあります。コンテンツの一部は、クラスがロードされた後、メソッド領域のランタイム定数プールに保存されます。
ダイレクト メモリ: - ダイレクト メモリはオフヒープ メモリとも呼ばれ、仮想マシンの実行時にはデータ領域の一部ではありません
。 NIO クラスは、JDK1.4 の後に導入されました。これは、チャネルとバッファーに基づく I/O メソッドであり、Nativefunctionライブラリを使用してヒープの外にメモリを直接割り当て、それを Java ヒープの DirectByteBuffer に保存できます。オブジェクトは、このメモリを操作するための参照として使用されます。これにより、パフォーマンスが大幅に向上し、Java ヒープとネイティブ ヒープの間でのデータの往復コピーが回避されます。
以下のように表形式にまとめます:
データ領域 | 概要 | スレッド共有 |
---|---|---|
プログラムカウンター | 現在のスレッドによって実行されたバイトコードの行番号インジケーター | いいえ |
仮想マシンスタック | Javaメソッド実行用ローカル変数、オペランド スタック、ダイナミック リンク、メソッド出口、その他の情報を保存するスタック フレームを作成します | いいえ |
ローカル メソッド スタック | 仮想マシン スタックと同様に、ネイティブ メソッドを提供します | いいえ |
スタック | オブジェクト インスタンスを格納します | は |
メソッド領域です | ロードされたクラス情報、定数、静的変数、オンザフライでコンパイルされたコード、および仮想マシンのその他のデータを格納します | は |
ランタイム定数プール | コンパイル中に生成されたリテラルとシンボル参照を格納するメソッド領域の一部 | は、 |
ヒープの外に割り当てられたダイレクトメモリ | メモリであり、パフォーマンスが高く、Javaのサイズによって制限されませんヒープ | は |
2. オブジェクトの作成とメモリのレイアウト
1. オブジェクトの作成
Java オブジェクトの作成
上の図はオブジェクト作成の完全なフローチャートであり、以下で詳しく説明します。
仮想マシンがnew命令を受け取ると、この命令のパラメータが定数プール内のクラスのシンボリック参照を見つけられるかどうかをチェックし、このシンボリック参照によって表されるクラスがロードされているかどうかをチェックします。そして解析され初期化されます 。そうでない場合は、クラスのロード プロセスを最初に実行する必要があります。
クラスのロードが完了すると、オブジェクトの割り当てに必要なスペースを決定できます。 Java ヒープ内のメモリが完全に規則的で、一方の側に使用済みメモリが保存され、もう一方の側に空きメモリが保存され、境界点のインジケータとして中央にポインタがある場合、メモリの割り当ては単に移動するだけです。ポインタを一定量だけ空き領域に向けて配置します。この配置方法は「ポインタ衝突」と呼ばれます。 Java ヒープ内のメモリが規則的ではなく、空きメモリと使用済みメモリがインターリーブされている場合、仮想マシンは使用可能なメモリ ブロックを記録するリストを維持し、オブジェクト インスタンスとメモリを割り当てるときに、リストから割り当てる十分な領域を見つけ出す必要があります。 リストのレコードを更新します。この割り当て方法は「フリーリスト」と呼ばれます。どの割り当て方法が使用されるかは、通常、仮想マシンのガベージ コレクターにコンパクション機能があるかどうかによって決まります。
- 利用可能なスペースを分割するとき、オブジェクトインスタンスにスペースを割り当てるときにスレッド
セーフであるかどうかも考慮する必要があります。スレッドの安全性を確保するには、2 つのオプションがあります。 1 つは、メモリ領域を割り当てるアクションを同期することです。実際、仮想マシンは更新操作のアトミック性を確保するために、失敗による再試行を伴う CAS を使用します。もう 1 つは、メモリ割り当てアクションをスレッドごとに異なる領域に分割することです。各スレッドは、ローカル スレッド割り当てバッファ(スレッド ローカル割り当てバッファ、TLAB) と呼ばれる、Java ヒープ内の小さなメモリを事前に割り当てます。メモリを割り当てたいスレッドは、そのスレッドの TLAB にメモリを割り当てます。同期ロックは、TLAB が使い果たされ、新しい TLAB が割り当てられる場合にのみ必要になります。
メモリ割り当てが完了すると、仮想マシンは に割り当てられたメモリ空間をゼロ値 - (オブジェクト ヘッダーを除く) に初期化し、オブジェクトのインスタンス フィールドが初期値を割り当てずに Java コードで直接使用できるようにします。価値観。
仮想マシンは、オブジェクトの
情報をオブジェクトのオブジェクト ヘッダー - に置きます。
- 2. オブジェクトのメモリ レイアウト
オブジェクトのメモリ レイアウトは 3 つの部分に分かれています:
- オブジェクトヘッダー
- 主に 2 つの情報部分が含まれます:
- ステータス
- フラグ、スレッドが保持するロックなど、オブジェクト自体の
実行時データ を保存するために使用されます。偏ったスレッドID、偏ったタイムスタンプなど。
もう 1 つの部分は type pointer - で、仮想マシンはこのポインターを使用して、オブジェクトがどのクラスのインスタンスであるかを判断します。オブジェクトが Java
3. メモリのリサイクル
1. オブジェクトの生存判定
Java 仮想マシンは、到達可能性分析 を通じてオブジェクトが生存しているかどうかを判定します。このアルゴリズムの基本的な考え方は、「GC ルート」と呼ばれる一連のオブジェクトを開始点として使用し、オブジェクトが GC ルートに到達したときにこれらのノードから下方向に探索するパスを参照チェーンと呼びます。参照がない場合、チェーンが接続されている間、オブジェクトは使用できません。 図に示すように、object
5、object6、object7は相互に関連していますが、GCルートに到達できないため、再利用可能なオブジェクトと判断されます。 もう 1 つ言及する価値があるのは、参照カウント メソッドでは、オブジェクトへの参照があるたびにカウンター値が 1 ずつ増加し、参照が失敗するとカウンター値が 1 ずつ減少します。 1 つ; いつでも カウンタが 0 のオブジェクトは使用できなくなります。参照カウンターは効率的で実装が簡単です。ただし、オブジェクト間の循環参照の問題を解決するのは困難です。ほとんどすべての主流の Java 仮想マシンは、メモリの管理に参照カウントを使用しなくなりました。
到達可能性分析の概念図
到達可能性分析アルゴリズムで到達不可能なオブジェクトであっても、すぐに再利用されない場合があります。オブジェクトをリサイクルする場合、少なくとも 2 回マーキング プロセスを通過する必要があります。
final
ize() メソッドを実行する必要があるかどうかです。オブジェクトが Finalize() メソッドをカバーしていない場合、または仮想マシンによって Finalize() メソッドが呼び出された場合、仮想マシンはこれら 2 つの状況を「実行する必要がない」ものとして扱います。このオブジェクトが Finalize() メソッドの実行に必要であると判断された場合、オブジェクトは F-Queue
キューに配置され、その後、優先度
の低いファイナライザー スレッドが仮想マシンによって自動的に作成されますFinalize() メソッドを実行します。 GC は、F キュー内のオブジェクトに対して 2 回目の小規模マークを実行します。そのオブジェクトが参照チェーン上のいずれかのオブジェクトに再度関連付けられると、そのオブジェクトは 2 回目のマーク中に「すぐにリサイクルされる」コレクションから削除されます。 。そうしないと、オブジェクトは実際にリサイクルされてしまいます。
メソッドのファイナライズ
2. メソッド領域のリサイクルの決定
メソッド領域のリサイクルには主に、
放棄された定数と
不要なクラスの2つの部分が含まれます。 破棄された定数のリサイクルは、Java ヒープ内のオブジェクトのリサイクルに似ています。
役に立たないクラスを判断するための条件は、次の 3 つの条件を満たす必要があります:
- このクラスのすべてのインスタンスはリサイクルされています。
マーク スイープ アルゴリズム (マーク スイープ)
:- アルゴリズムは、「マーキング」と「クリア」の 2 つの段階に分かれています。まず、必要なオブジェクトをマークします。マーキングが完了した後、マーキングされたオブジェクトは一律にリサイクルされます。それには主な欠点が 2 つあります。1 つは効率の問題
- 、マーキングとクリアのプロセスがあまり効率的ではないことです。 2 つ目は、
スペースの問題です。マークがクリアされた後、大量の不連続なメモリ フラグメントが生成されるため、より大きなオブジェクトが割り当てられたときにメモリ スペースが不足する可能性があり、ガベージ コレクション アクションが必要になります。事前に発動される。
マーククリア
コピーアルゴリズム:
コピーアルゴリズムは、容量に応じて利用可能なメモリを2つの等しいサイズのブロックに分割し、一度にそのうちの1つだけを使用します。メモリのブロックが足りなくなったら、残っている オブジェクトを別のブロックにコピーし、使用されているメモリ領域を一度にクリーンアップします。このように、毎回半分の領域全体がリサイクルされ、メモリを割り当てるときにメモリの断片化を考慮する必要がなく、ヒープの先頭ポインタを移動して順番にメモリを割り当てるだけで実装が簡単で効率的です。ただ、このアルゴリズムでは - メモリが元のサイズの半分
に削減され、その分コストが高くなります。
コピーアルゴリズム
-
Mark-Compact(Mark-Compact)
:
マーキングプロセスは「マーククリア」アルゴリズムと同じですが、その後のリサイクル可能なオブジェクトのクリーニングは異なります直接実行されますが、すべての生きているオブジェクトを一方の端に移動させ、端の境界の外側のメモリを直接クリーンアップします
Mark-Complete アルゴリズム
4.世代別コレクション アルゴリズム
のガベージ コレクション商用仮想マシン 世代別コレクション アルゴリズムを使用して、オブジェクトの生存サイクルに従ってメモリをいくつかのブロックに分割します。 Javaヒープは新世代と旧世代
-
ほとんどの場合、オブジェクトは新世代 Eden 領域に割り当てられます。 Eden 領域に割り当てる十分なスペースがない場合、仮想マシンはマイナー GC を開始します。 GC 後、オブジェクトは Survivor 空間に配置されようとしますが、Survivor 空間にオブジェクトを配置できない場合は、空間割り当て保証メカニズムを通じて事前に古い世代にオブジェクトを転送することしかできません。
オブジェクトは Eden パーティションで優先されます: -
ラージ オブジェクトは、大量の連続メモリ領域を必要とする Java オブジェクトを指します。仮想マシンは -XX:PretenureSizeThreshold パラメータを提供します。オブジェクトがこの設定値より大きい場合、オブジェクトは古い世代に直接割り当てられます。これにより、新世代の Eden 領域と 2 つの Survivor 領域での大量のメモリのコピーを回避できます。
ラージ オブジェクトは古い世代に直接入ります: -
仮想マシンは、オブジェクトごとにオブジェクト経過時間カウンターを定義します。オブジェクトがエデンで生まれ、マイナー GC 後も存続し、サバイバーによって収容できる場合、そのオブジェクトはサバイバー スペースに移動され、オブジェクトの年齢は 1 に設定されます。各マイナー GC 後もオブジェクトは存続します。 Survivor エリアに、年齢を 1 つ追加するだけで、年齢が -XX:MaxTenuringThreshold パラメーターで設定された値に達すると、古い世代に移動されます。
長期的に存続するオブジェクトは古い世代に入ります: -
仮想マシンは、オブジェクトを古い世代に移動する前に、オブジェクトの年齢が -XX:MaxTenuringThreshold で設定された値に達する必要があるとは限りません。 Survivor 内の同じ年齢のすべてのオブジェクトのサイズの合計が Survivor スペースの半分より大きい場合、この年齢以上の年齢のオブジェクトは直接古い世代に入ることができます。
動的な年齢判断: -
マイナー GC の前に、仮想マシンは古い世代の利用可能な最大連続スペースが新しい世代のすべてのオブジェクトの合計スペースより大きいかどうかを確認し、条件が true の場合、マイナー GC を実行します。 GCが確立されます。そうでない場合、仮想マシンは HandlePromotionFailure 設定値が保証失敗を許可するかどうかをチェックします。許可されている場合、古い世代で使用可能な最大連続領域が古い世代に移動されたオブジェクトの平均サイズより大きいかどうかのチェックが続行され、それが大きい場合は、マイナー GC が試行されます。それが小さい場合、または HandlePromotionFailure 設定値がリスクを許容しない場合、フル GC が実行されます。
スペース割り当ての保証:
新世代 GC (マイナー GC): 新世代で発生するガベージ コレクション アクション。ほとんどの Java オブジェクトは生成されて消滅するため、マイナー GC は非常に頻繁に発生し、リサイクル速度も高速です。
旧世代 GC (メジャー GC/フル GC): 旧世代で発生するガベージ コレクション アクション。メジャー GC には、少なくとも 1 つのマイナー GC が伴うことがよくあります。メジャー GC の速度は、通常、マイナー GC よりも 10 倍以上遅くなります。
🎜以上がJava メモリの割り当てとリサイクルのメカニズムの詳細な説明 (図)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

この記事では、Javaプロジェクト管理、自動化の構築、依存関係の解像度にMavenとGradleを使用して、アプローチと最適化戦略を比較して説明します。

この記事では、MavenやGradleなどのツールを使用して、適切なバージョン化と依存関係管理を使用して、カスタムJavaライブラリ(JARファイル)の作成と使用について説明します。

この記事では、カフェインとグアバキャッシュを使用してJavaでマルチレベルキャッシュを実装してアプリケーションのパフォーマンスを向上させています。セットアップ、統合、パフォーマンスの利点をカバーし、構成と立ち退きポリシー管理Best Pra

この記事では、キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPAを使用することについて説明します。潜在的な落とし穴を強調しながら、パフォーマンスを最適化するためのセットアップ、エンティティマッピング、およびベストプラクティスをカバーしています。[159文字]

Javaのクラスロードには、ブートストラップ、拡張機能、およびアプリケーションクラスローダーを備えた階層システムを使用して、クラスの読み込み、リンク、および初期化が含まれます。親の委任モデルは、コアクラスが最初にロードされ、カスタムクラスのLOAに影響を与えることを保証します


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

SublimeText3 英語版
推奨: Win バージョン、コードプロンプトをサポート!

Safe Exam Browser
Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

ZendStudio 13.5.1 Mac
強力な PHP 統合開発環境

Dreamweaver Mac版
ビジュアル Web 開発ツール

ドリームウィーバー CS6
ビジュアル Web 開発ツール
