序文
GC
中国の通訳のガベージコレクションは、メモリリークを回避するために、メモリ空間の再利用の仕組みです。ときにJVM
メモリが実行することにより、タイトであるGC
リユースメモリを有効に順番に新しいオブジェクトに割り当てられたメモリの効果的な回復を。JVM
GC
、積極的な参加のためのメカニズムを開発する彼らの作業負荷を減らすが、いくつかのケースでは、自動的にする必要があるが、GC
私たちは理解して進めるために必要がある、減少したシステム性能、応答が遅いにつながるGC
メカニズムを。このような状況に直面したとき、穏やかにするためには、問題を解決します。さらに、GC
メカニズムもされJava
、高周波の質問を面接GCが不可欠なスキルであることを理解します。
研究GC
、我々は最初の三つの問題を解決します:
- ゴミは何ですか
- どこごみ
- どのようにごみ
ゴミは何ですか
コードのシンプルな作品で見てみましょう。
バイト配列に文字列にオブジェクトを介して、上記コードは、その後、ローカルファイルに書き込まれます。開始方法と、それは新しいオブジェクトのいくつかのメモリを割り当て、その後の参照を教えてくれますstr
、bytes
変数。メソッドが終了するまで、内部メソッドのローカル変数はすぐに破棄されます。しかし、これはローカル変数の破壊であるが、実際のオブジェクトはメモリを奪うしません。アクティブなオブジェクトが参照されていないこのようなことは、もはや、それはスパムとして分類されませんされています。
それは巨大なメモリ内の無数のオブジェクトを生き延びたGC
ことを正確にライブオブジェクトとガベージオブジェクトに分け、これらのオブジェクトをマークするために必要とされる前に。このプロセスは、以下にマークされると、私たちは次を待つことができGC
、マークリサイクル、これはGCの効率に影響を与えます。また、間違ったマーク、通常のライブオブジェクトは、スパムとしてマークされたことはありません。オブジェクトたら、通常の生存の回復は、各種プログラムの崩壊につながる可能性があります。
マークに使用できる2つのアルゴリズムがあります。
- 参照カウント
- 到達可能性解析
参照カウント
オブジェクトヘッダフィールドを割り当てて参照カウントは、オブジェクトの参照カウントが記憶されます。オブジェクトが他のオブジェクトによって参照されると、カウントがインクリメントされます。これが失敗した場合、参照カウントがデクリメントされます。基準カウント値は、オブジェクトがもはや参照されていることを示していない場合には、回収することができます。
上記の図は、場合str
カウント値として、ヒープ上のオブジェクトを参照します。ときにstr
変更がnull
いずれかのオブジェクトが参照されなくなったときに、カウント値が1だけ減算されません。この時点で、オブジェクトができますGC
回復しました。
カウント値のみをカウントリファレンスは、このプロセスは、より効率的で、達成することは比較的簡単です。しかし、オブジェクト循環参照の問題を解決していない、非常に深刻な問題があります。
図から分かる、a
、b
それはもはや1でカウントにつながる、ヒープオブジェクトを参照されません。互いへの2つのオブジェクトの内部参照がある。この場合、カウント値は、0ではないではないGC
オブジェクトを回収する方法。
到達可能性解析
アルゴリズムは最初のルールに現在アクティブな記載への参照を見つける必要がある、それが参照されますGC Roots
。次に、GC Roots
ルートノードビューとして、オブジェクト参照グラフをトラバース、無駄なオブジェクトとして残りのオブジェクト、オブジェクトが生存のためにマークされている(最大)を横断することができるであろう。
そのイエスの注意参照ではなく、オブジェクトを。
緑色の円形の参照オブジェクトが存在するが、それは、図から分かるように、これらのオブジェクトはできないのでGC Roots
、それは回収され、トラバース。
それは次のように使用することができGC Roots
、アクティブで引用した参考文献は含むが、以下に限定されるものではありません。
- ローカル変数の方法
- 静的変数、定数
- JNIハンドル
- ....
どこごみ
接触の始まりを覚えてJava
、スタックが唯一知っている、ヒープに割り当てられたオブジェクトのインスタンスは、この方法は、ローカル変数をスタックに位置しています。実際JVM
のメモリ領域に分かれ、より細かく分割されます。
- ヒープ
- メソッド地区
- VMスタック
- ネイティブメソッドスタック
- プログラムカウンタ
示されているように、私たちのメモリは、スレッドに分割され、スレッドがプライベートエリアを共有しています。メソッドは、スレッドのスタック領域と共有領域は、二つの部分が占有しているJVM
メモリのほとんどを、残りの3つは、スレッドダイと、それが自動的にされますが、スレッドと弟をバインドされますJVM
回復しました。
ヒープ
ヒープは、仮想マシンであり、それは単に、通常最大メモリ上の領域を占有し、ほぼすべてのオブジェクトインスタンスがここに誕生します、最も身近1エリアでなければなりませんJVM
ビッグブラザーのメモリ。ヒープ内部メモリは単純なものではない、異なるオブジェクトが異なる領域に配置され、現在の世代のアルゴリズム、世代ヒープに基づいて説明します。これは、我々は再び以下に詳細に理解ものです。
メソッド地区
地区メソッドは、情報クラス情報は、仮想、定数、静的変数、バイトコードの上にロードされている保存されます、ヒープは、メソッド領域で公式情報をオブジェクト、あなたは右のそれを作成することができます。
スタック
VMスタックのスタックフレームは、一連のスタックで構成され、各スタックフレームは、メソッドの実際の代表である、それはスタックフレーム内のローカル変数テーブル方式、方法ゲート情報、および他のオペランドスタックに保存されます。あなたがメソッドを呼び出すたびに、それがスタックスタックフレーム、実行が終了すると、スタックに置かれます。
ネイティブメソッドスタックとより類似した仮想マシンを積み重ね、最大の違いは、仮想マシンのスタックの実行ということであるJava
ネイティブメソッドスタックを実行するために使用される一方で、法Native
のサービスの方法を。以下の方法は、ネイティブメソッドスタックで実行されます。
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
复制代码
プログラムカウンタ
プログラムは、いくつかの計算は、地域のこの部分は、最小で占められていると言えるが、機能は非常に重要です。コンパイラによるJavaソースコードはバイトコードとなり、その後、JVMを実行した後にロードされ、ディレクティブとなり、プログラムカウンタの仕事は、現在の命令の実行スレッドを指示する必要があります。だから、スレッド切り替えが発生した場合でも、回復を待っている間に、現在のスレッドは、まだ次の命令を知っていることを実行します。
どのようにリサイクル
現在主流のGCアルゴリズムは3種類に分けられます。
- マーク - スイープアルゴリズム
- レプリケーションのアルゴリズム
- マーク - 照合アルゴリズム
マーク - スイープアルゴリズム
このアルゴリズムは、最も基本的かつ最も容易に達成の一つであり、主な実装手順は、2つのステップに分かれています:マーキング、明確な。
- タグ:上記
GC Roots
対象フラグアップ。 - クリア:クリーンマークされていないオブジェクト。
PS:このマップは、ああを描くのは本当に難しいです。。。。
このアルゴリズムは、ヒープスペースが一掃されるものの、回復後に見られるだけでなく、たくさん持っていることができるスペースデブリのを。これは、新しいオブジェクトがヒープの残量に基づいて計算さにつながる、ルックスは、実際の割り当てプロセスは、仮想マシン対応のメモリ不足で、その結果、何の連続したメモリがないため、割り当てられることができるが、彼らは再び火を余儀なくされていますGC
。
ここでは、おそらく、オブジェクトが連続したメモリのブロックを割り当てる必要がなぜ、疑問を持っているのだろうか?
ここでR神、それを引用する@RednaxelaFXの答えを。
また、このアルゴリズムの不足している:クリア標識化および効率が比較的低いです。これはさえにつながる可能性がありGC
、通常のプログラムに影響を与え、あまりにも長く取ります。
レプリケーションのアルゴリズム
効率の問題を解決するために、複製アルゴリズムを生まれ。このアルゴリズム使用可能なメモリは、それぞれが一つだけ、メモリのこの作品を使い切ったときに、トリガが使用し、2分割されGC
、その後、ワンタイムメモリをクリーンアップするために使用されてきた入れ、別の部分に複製するために、オブジェクトの生存期間となりますが。
各動作のアルゴリズムは、メモリの半分だけを必要と、GC
新しいオブジェクトのメモリ割り当ては、メモリがシンプルで効率的な操作を実現するために割り当てられている場合のみ、スタックポインタの上部が移動しても回復した後、任意のスペースデブリがあります。しかし、このアルゴリズムは、メモリ空間のアイドル半分は、スペース効率が高くない、です。
PS:時間のレプリケーションアルゴリズム空間は、二人は両方を持つことができません
また、オブジェクトの生存期間もアルゴリズムの複製効率に影響を与えます。対象は主に死に向かって生の夜であれば、ちょうどあなたがスペースのほとんどを解放することができ、ライブオブジェクトの少量を移動する必要があります。オブジェクトが、生存率は頻繁にトリガーにつながる可能性が回復した後、よりコピー操作、およびまた、余分なメモリを必要とし、高い場合GC
。
ソートアルゴリズム - この長い時間のオブジェクトの生存のために、我々はマークを使用する必要があります。
マーク - 照合アルゴリズム
マーク - ソートアルゴリズムをマークすることができます - クリアは、アルゴリズムのバージョンを改善スペースデブリの問題が原因クリア向上します。このアルゴリズムは、2つのステップに分かれています。
- タグ:によっても
GC Roots
ライブオブジェクトをマーク。 - 仕上げ:ダイレクト・メモリのクリーンアップよりも境界の終わり、その後、最初の並べ替えのメモリアドレスに応じて、最後にライブオブジェクトを動かします。
マークが、 - マークを解決するためのアルゴリズムのソート - スペースデブリのスイープアルゴリズム、全メモリ空間のもフルに活用しますが、この問題は非常に効率的なアルゴリズムではありません。マークに比べ - 掃引アルゴリズム、マーク - スイープアルゴリズム - ソートアルゴリズムは、より多くのこのステップを終了増加よりも、アルゴリズムの効率も低いマークよりなります。
世代別コレクションアルゴリズム
3種類の上からGC
アルゴリズムを見て、空間と時間効率のいずれも比較的完璧なアルゴリズムではないことができ、我々は行うことができますメモリの未使用領域に適用される様々なアルゴリズムの総合利用の特徴です。
異なるオブジェクトの生存期間に基づいて、現在市販されている仮想マシンは、一般的に新世代、古い時代に分け、メモリ領域を分割しました。新しいオブジェクトは、一般的に割り当てられた生存期間が一定の閾値よりも大きい場合、それは古い時代に移動されますオブジェクトの後に、新しい世代への新世代を優先させて頂きます。短命オブジェクトの新しい世代が幽霊ある、古い時代には、オブジェクト氏の長寿です。
すべての新しい世代のGC
オブジェクトの後には、それが複製アルゴリズムに適している、大量にリサイクルすることができ、唯一のライブオブジェクトの少量をコピーするコストを支払う必要があります。ここではメモリが分割されていない1:1つの部門は、デフォルトでは8に従います:1:1に分かれているEden
と2 Survivor
スペース。それぞれの使用Eden
とのSurvivor
スペースは、私たちは単にメモリ空間の10%をアイドル。しかし、我々は、オブジェクトの生存と回復を確実にすることはできませんたびに、あなたが老後を確保したメモリの割り当てに依存する必要があり、その場合には10%未満、です。ときにSurvivor
スペースが残っているライブオブジェクトを保存しません、これらのオブジェクトは、バイナリ歳を保証するために配布を通って移動します。
スイープやマーク - - ソートアルゴリズム旧の生存オブジェクトが特に高くなり、余分なスペースが割り当てられる保証はありません、それは複製アルゴリズムに適していない、マークを使用する必要があります。
ただ、話
最近、今年最終試験の時間は、再学習に「Java仮想マシン・深さで」周志明を拾っていました。この本を見て最初の時間を覚えて、コンテンツの多くは読み取ることができない、忘れてすぐに読みます。その後、いくつかの時間後、再び本をピックアップし、より良い最後の時間よりも、この時間は、我々は少しの半分以上を参照することができました。最近のいくつかの小さなチャットとのパートナーシップ、彼らはすべてこの本は学ぶために読んでことがわかったがJVM
、この本は本当に神の書物であることを言わなければなりません。最近の「徹底的なJava仮想マシン、」第三版が販売されてすぐに来て、少し必要パートナーを開始考えることができるがあります。
さて、GC
ここに次のJVM共通程度のletの話を要約するメカニズムGC
コレクタを。
ヘルプリンク
ルーツGC Java仮想マシン04詳しい---- GCアルゴリズムとの種類の深いJava仮想マシン
インタプリタプログラム、および取得毎日ドライプッシュ:私は公共の数の関心を歓迎します。:あなたは私のトピックの内容に興味があるなら、あなたは私のブログに焦点を当てることができstudyidea.cn