この記事の内容は、Java のメモリ メカニズムと GC リサイクル メカニズムの分析に関するものです (写真とテキストでの紹介)。必要な方は参考にしていただければ幸いです。
Java コードの実行とコンパイルのプロセス
Java メモリ管理
Java メモリ モデル部門
##オブジェクトの位置決めへのアクセス
#
Object obj = new Object();
Java オブジェクトの作成と初期化
Java オブジェクトが作成されると、ヒープ メモリ内に独自の領域が確保され、続いてオブジェクトの初期化プロセスが行われます。クラス メンバーの初期化シーケンスの概要: 最初に静的、次に通常、次にコンストラクト、最初に親クラス、次に子クラス、および同じレベルでの書き込み順序
親クラスを実行する静的変数と静的コード ブロックを最初に実行し、次にサブクラスの静的変数と静的コード ブロックを実行します。#静的メソッドの初期化は通常のメソッドに先行します、静的初期化は必要な場合にのみ実行され、初期化は 1 回だけ行われます。
注: サブクラスのコンストラクターの場合、コンストラクターがパラメーターを受け取るかどうかに関係なく、デフォルトでは、パラメーターを持たない親クラスのコンストラクターが最初に検索されます。親クラスにパラメーターのないコンストラクターがない場合、サブクラスは supper キーを使用してパラメーター付きの親クラスのコンストラクターを呼び出す必要があります。そうしないとコンパイルが成功しません。
Java のガベージ コレクターは、不要なオブジェクトによって占有されているメモリを自動的に再利用できますが、その役割は、Java で作成されたオブジェクトによって占有されているすべてのメモリを解放することだけです。 Java では、オブジェクトの作成以外の何らかの方法でオブジェクトに割り当てられたメモリ空間はガベージ コレクタによって再利用できません。また、ガベージ コレクション自体にもオーバーヘッドがあり、GC の優先順位は比較的低いため、JVM がメモリに直面しない場合は、メモリを復元するためのガベージ コレクションにリソースが無駄になります。最後に、プログラムがストレージ領域を使い果たさない限り、オブジェクトが占有している領域は決して解放されないことがわかります。コード System.gc() を使用してガベージ コレクターをアクティブに開始できます (ただし、JVM はすぐにはリサイクルしません)。 new によって割り当てられたメモリ領域を解放する前に、他のメソッドによって割り当てられたメモリ領域が Finalize() によって解放されます。
どのメモリをリサイクルする必要があるかJava ヒープおよびメソッド領域のメモリ
リサイクルする場合
参照カウント方法
参照する場所があるたびに、オブジェクトに参照カウンタを追加します。それ、カウンタープラスワンです。一方、参照が無効になるたびに、カウンタは 1 ずつ減らされます。カウンタが 0 の場合、オブジェクトが参照されていないことを意味します。例:
#到達可能性分析
複数のルート オブジェクト (GC ルート) を設定します。各オブジェクトはルートを見つけられない場合、オブジェクトとみなされます。到達不能。
マーク消去アルゴリズム
まず、リサイクルする必要があるすべてのオブジェクトにマークを付けます。マークが完了すると、マークされたすべてのオブジェクトが均一にリサイクルされます。
このアルゴリズムには 2 つの問題があります: 1) マーキングとクリアのプロセスは効率的ではありません。主な理由は、ガベージ コレクターは GC ルート ルート オブジェクトから到達可能なすべてのオブジェクトを走査し、クリーンアップ中にこのオブジェクトがスキップされることを示すマークをこれらのオブジェクトに追加する必要があるためです。その後、クリーンアップ フェーズ中にガベージ コレクターが Java ヒープから開始されます。オブジェクトがマークされていない場合、オブジェクトはクリアされます。明らかに、トラバーサルの効率は非常に低くなります。2) 大量の不連続なスペース フラグメントが生成されるため、プログラムの実行中により大きなオブジェクトを割り当てる必要がある場合、十分なメモリを見つけることができず、事前にガベージ コレクションを開始します。
コピー アルゴリズム
メモリを 2 つのブロックに分割し、一度に 1 つのブロックのみを使用します。このメモリ ブロックがいっぱいになると、残ったオブジェクトが別のブロックにコピーされ、メモリ アドレスに従って厳密に配置され、使用されたメモリ ブロックが均一にリサイクルされます。
利点は: 連続したメモリ空間を取得できることです。
欠点は: メモリの半分が無駄になることです
最新の JVM はメモリ空間を 1:1 に従って分割せず、より大きなメモリ空間に分割します。 Eden エリアと 2 つの小さな Survivor エリア (Eden エリアと Survivor エリア) が毎回使用されます。リサイクルする場合は、エデンとサバイバーに残っているオブジェクトを別のサバイバーに一度にコピーし、最後にエデンとサバイバーのスペースをクリーンアップします。実際、ここには別の疑問があります。ガベージ コレクションの後、生き残ったオブジェクトが必要とするスペースが、Survivor の残りのスペースよりも大きい場合はどうなるでしょうか。答えは、割り当てを他のメモリに依存する必要があるということです (ここでは主に古い世代を指します)。
Mark-Complete アルゴリズム
このプロセスは、Mark-Clear アルゴリズムと同じですが、マークされていないメモリ領域は後で消去されない点が異なります。 2 つ目は、残っているすべてのオブジェクトを一方の端に移動し、境界の外側のメモリをクリーンアップすることです。
生成アルゴリズム
いわゆる世代 オブジェクトのライフサイクルに従ってメモリをいくつかのブロックに分割し、オブジェクトの「年齢」に応じて適切なガベージ コレクション アルゴリズムを選択できるようにします。 Java では、メモリ内のオブジェクトはそのライフスパンに従って次のように分類されます。 1. 新しい世代: ローカル変数などの短いライフ サイクル、 2. 古い世代: 長いライフ サイクルのオブジェクト、 3. 永続的な世代: ほとんどリサイクルされない、長いライフ サイクル。ロードされたクラス情報など。
新世代と旧世代はヒープ領域に、永続世代はメソッド領域に格納されます。非常に長い文字列や大きな配列など、大きなオブジェクトは古い世代に直接入ります。大きなオブジェクトは連続したメモリを見つける必要があるため、大きなオブジェクトは連続したメモリを見つける必要があり、そうしないと GC がトリガーされるため、存続期間の短い大きなオブジェクトが発生します。必要ですので避けてください。長期間存続したオブジェクトは、新しい世代でマイナー gc が発生するたびに、その年齢が 1 ずつ増加します。デフォルトでは、オブジェクトは 15 歳に達すると古い世代に入ります。各マイナー GC 中に、仮想マシンは古い世代に昇格された平均サイズが古い世代の現在の残りのサイズより大きいかどうかを検出し、小さい場合はフル GC が実行されます。
新世代では、コピー アルゴリズムが使用されます (生き残っているオブジェクトが少なく、死んだオブジェクトが多すぎるためです。マーククリア アルゴリズムを使用する場合は、マークをトラバースする必要があり、明らかに効率が低くなります。ただし、コピーを使用すると、古い世代は生存率が高いため、マーク クリアまたはマーク ソート アルゴリズムを使用してリサイクルします。
以上がJavaのメモリ機構とGCリサイクル機構の解析(写真と文章による紹介)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。