1.説明
- プログラムカウンター、仮想マシンスタック、ローカルメソッドスタックの3つの領域は、スレッドで生成され、スレッドで破棄されます。これらの領域のメモリ割り当てとリサイクルは決定的です
- Javaヒープとメソッド領域のこの部分のメモリ割り当てとコレクションは動的であり、ガベージコレクターはこのメモリの部分を懸念しています
新世代と旧世代
Javaのヒープは、JVMが管理する最大のメモリ空間であり、主にさまざまなクラスのインスタンスオブジェクトを格納するために使用されます。
Javaでは、ヒープは2つの異なる領域に分割されます。若い世代(Old)と古い世代(Old)です。新世代(ヤング)は、エデン、サバイバーから、サバイバーへという3つの領域に分かれています。
ヒープのメモリモデルはおおよそ次のとおりです。
ヒープサイズ=新世代+古い世代。
ガベージコレクションは、通常、Javaヒープで発生します。
メソッド領域は永続的な世代と呼ばれます。
新生代:
被験者の生存率は低いです。
古い世代:
被験者の生存率は高いです。
2.ヒープ内のオブジェクトが死んでいるかどうかを判断する(どのような方法でも使用できなくなったオブジェクト)
2.1参照カウントアルゴリズム
意味:
参照カウンタをオブジェクトに追加します。参照がある場合は、カウンタがインクリメントされます。参照が無効な場合は、カウンタがデクリメントされます。カウンタが0になると、オブジェクトを使用できなくなります。
短所:
オブジェクト間の循環参照の問題を解決することは困難です。
例:
次の例:OBJAは、オブジェクトとオブジェクトはobjBフィールドインスタンスを持って、作るために割り当てられているobjA.instance = objB
とobjB.instance = objA
、加えて、二つのオブジェクト2つのオブジェクトが訪問することは不可能だったという事実を参照せず、しかし、彼らはお互いに参照しているため相手側。参照カウントが0ではないため、参照カウントアルゴリズムはGCコレクターを介してそれらをリサイクルできません。
public class ReferenceCountingGC {
public Object instance = null; private static final int _1MB = 1024 * 1024; // 这个成员属性的唯一意义就是占点内存,以便能在GC 日志中看清楚是否被回收过 private byte[] bigSize = new byte[2 * _1MB]; public static void main(String[] args) { ReferenceCountingGC objA = new ReferenceCountingGC(); ReferenceCountingGC objB = new ReferenceCountingGC(); objA.instance = objB; objB.instance = objA; objA = null; objB = null // 假设在这行发生 GC,那么 objA 和 objB 是否能被回收 System.gc(); } }
注: VMオプション構成パラメーター:-verbose:gc -XX:+PrintGCDetails
部分的な印刷結果は次のとおりです。
[GC (System.gc()) [PSYoungGen: 6772K->680K(38400K)] 6772K->680K(125952K), 0.0098335 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] [Full GC (System.gc()) [PSYoungGen: 680K->0K(38400K)] [ParOldGen: 0K->623K(87552K)] 680K->623K(125952K), [Metaspace: 3213K->3213K(1056768K)], 0.0145286 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
結果はGCログで確認できます6772K->680K
。これは、2つのオブジェクトが相互に参照しているため、仮想マシンがリサイクルしないことを意味します。これは、仮想マシンが参照カウントアルゴリズムを使用してオブジェクトが有効かどうかを判断しないことを示します。
2.2。ルート検索アルゴリズム(到達可能性分析アルゴリズム)
意味:
「GC Roots」という名前の一連のオブジェクトを起点として、これらのノードから下方向に検索します。検索がたどるパスは参照チェーンと呼ばれます。オブジェクトが参照チェーンなしでGC Rootに接続されている場合(グラフ理論を使用)言い換えれば、GC Rootsからこのオブジェクトに到達できない場合)、このオブジェクトが使用できないことが証明されます。
GC Roootオブジェクト:
- 仮想マシンスタック内の参照オブジェクト(スタックフレームのローカル変数テーブル)
- メソッド領域の静的クラスプロパティによって参照されるオブジェクト
- 定数によって参照されるオブジェクトに移動するメソッド
- ローカルメソッドスタックでJNI(つまり、一般にネイティブメソッド)によって参照されるオブジェクト
(メソッド領域とスタック内)
例:
オブジェクトobject5、object6、object7は互いに関連していますが、GCルートに到達できないため、リサイクル可能なオブジェクトと判断されます。
3.ガベージコレクションアルゴリズム
3.1 Mark-Clearアルゴリズム
意味:
最初に、回復が必要なすべてのオブジェクトにマークを付け、ラベル付けが完了した後、マークされたすべてのオブジェクトを収集します。
短所:
- 非効率的
- スペースデブリが多すぎる
例:
3.2コピーアルゴリズム(通常、新世代で使用されます)
意味:
使用可能なメモリを容量に応じて同じサイズの2つのブロックに分割し、一度に1つだけ使用します。このメモリブロックが使い果たされたら、残っているオブジェクトを別のブロックにコピーしてから、使用されているメモリ領域を一度クリーンアップします。
短所:
メモリをオリジナルの半分に減らすには、コストが高すぎます。
改善:
メモリを大きなエデンスペースと2つの小さなサバイバースペースに分割します。毎回、エデンとサバイバーの1つを使用します。リサイクルするときは、エデンとサバイバーに残っているオブジェクトを一度に別のサバイバースペースにコピーし、最後に使用したエデンとサバイバーのスペースをクリアします。
例:
3.3マーキングソートアルゴリズム(一般的に旧世代で使用されていました)
意味:
残っているすべてのオブジェクトを一方の端に移動させ、最後の境界を超えてメモリを直接クリーンアップします。
例:
3.4世代別収集アルゴリズム
意味:
メモリはオブジェクトのライフサイクルに応じていくつかのブロックに分割され、一般的にJavaヒープは新世代と旧世代に分けられ、各世代の特性に応じて最適な収集アルゴリズムが採用されます。
- 新世代:複製アルゴリズム
- 旧世代:Mark-Organize / Mark-Organize
今は基本的にこれを使います。
-----------------------------
元のリンク:https://www.jianshu.com/p/a0f4144356af