JavaのガベージコレクタのJavaのガベージコレクションとメモリ管理メカニズムの深い理解

アウトライン

我々は、すべてのJavaのメモリ管理は非常に「オートメーション」は遭難メモリ管理を避けることができるのJavaエンジニアに私たちを可能にしていることを知っているが、我々は学んでいるとメモリ割り当てのGCにも理にかなって:あなたはメモリオーバーフローのさまざまなトラブルシューティングを行う必要がある場合は、メモリリークとき、ガベージコレクションシステムは、高い並行性を達成するためのボトルネックになった場合にのみ、その原則を理解することによって、私たちはより良いこれらの問題を監視し、制御することができます。ガベージコレクション(ガベージコレクション、GC)と言えば、ほとんどの人は、Java言語のコンパニオン製品として、この技術を考えています。GCの中で実際に3つの問題に対処する必要がGCを考えることを理解し、学びたい人たちのすべてに値します:

1.どのようなメモリリサイクルする必要がありますか?2.場合は、メモリの回復?3.どのようにメモリを解放するには?

これらの3つの課題と考え、学び、そして私は私たちにJavaのガベージコレクションのメカニズムのより多くの理解を作ることができなければならないと考えています。


まず、最初の質問、見てメモリを回復するために必要ですか?私たちは、ほぼすべてのJavaヒープ内のオブジェクトのインスタンスを格納することを知って、リサイクルのためのヒープの前でガベージコレクタは、まず最初に、何が「死ぬ」されていると、これらのオブジェクトのどれがまだ「生きている」かを決定することである(つまり不可能その後、任意の手段によって参照されるオブジェクト)。そして、これらのオブジェクトの「死」は、我々はオブジェクトを回復する必要があるということです。ここでは、単にアルゴリズムの生存率は、使用するかどうかを判断するためのオブジェクトです。

まず、対象アルゴリズムの生存かどうかを決定します

1.参照カウントアルゴリズム(参照カウント)

アルゴリズム分析

参照カウントガベージコレクタの戦略は、早期にその原則的になっている参照が失敗作る際に、カウンタ値を1だけ減少する;それを参照する場所は、カウンタ値が1増加されるたびに、オブジェクトカウンターへの参照を追加するために、任意の時間カウンタオブジェクトの0を使用することはもはや不可能です。

長所と短所

長所:参照カウントコレクターは、プログラムの実行中にインターリーブ、迅速に行うことができます。より有利な手順は、長い時間リアルタイム環境のために中断する必要はありません。

短所:循環参照が検出することができません。親として、サブオブジェクト参照があり、順番に、親オブジェクトの子オブジェクト参照。このように、彼らは、参照カウントがゼロになることはありません。例えば、循環参照カウントアルゴリズムは、問題を解決することはできません参照します。

public class Main {    
       public static void main(String[] args) {
            MyObject object1 = new MyObject();        
            MyObject object2 = new MyObject();

            object1.object = object2;        
            object2.object = object1;

            object1 = null;        
            object2 = null;

           //假设在这行发生GC,object1和object2能否被回收?          
            System.gc();    
      }
 }复制代码

最後の二つの物体1直面するとオブジェクト2の割り当てがヌルである、すなわち、物体1とオブジェクト2点がもはやアクセスできない対象であったと言うことであるが、それらはお互いを参照するため、それらは、カウンタは、その後、ガベージコレクタ0でない参照させます彼らは回復しません。

この方法なので、(メモリ管理)かどうか、オブジェクトが生きているかを決定するために参照カウントアルゴリズムの選択肢を持っていない、現在の主流のJava仮想マシンに問題があるので、それは正確です。


前記到達可能性分析アルゴリズム(到達可能性分析)

アルゴリズムの2.1分析

主流のビジネス・アプリケーション(Javaの、C#)主流の実装では、音声、オブジェクトは(もルート検索アルゴリズムとして知られている)到達可能性解析アルゴリズムにより生き残っているかどうかを判断します。:アルゴリズムはグラフ理論の離散数学からでは、アルゴリズムの基本的な考え方がある導入ダウンこれらのノードから検索を開始するには、出発点として、「GCのルーツ」と呼ばれる一連のオブジェクトを通じ、走行道路が呼び出された検索しますGCルーツにオブジェクトがどのリストにも接続されていない基準鎖(refence鎖)、(グラフ理論の言葉では、このオブジェクトへのGCのルーツが到達不能である)場合、それは、このオブジェクトが利用できないことを証明しています次の図に示すが、object5オブジェクト、object6、object7が相互に関係しているが、彼らはGCのルーツまでではありませんので、彼らはリサイクル可能なオブジェクトであることが決定されるであろう。

Javaはオブジェクトが持っているGCのルーツとして使用することができます

参照1. VMスタックオブジェクト(ローカル変数テーブル)

2.静的プロパティ参照におけるオブジェクトのメソッド

3.一定の基準でオブジェクトのメソッド

4.ネイティブメソッドスタック(ネイティブオブジェクト)に参照されるオブジェクト


次に、我々は、2番目の質問について考える必要がメモリを再利用するために何時間?この問題は、アルゴリズムのホットスポットで答えを見つけることができ

二、HotSpotのアルゴリズム

1.列挙のルート

        到達可能性分析は、例えば、実行コンテキスト(例えば、ローカル変数スタック・フレーム・テーブルとプライマリノードGCルーツグローバル基準(例えば、一定または静的プロパティクラス)として使用することができ、GC根ノードから操作この基準チェーンを見つけるために)、および多くのアプリケーションのための今唯一の方法メガバイトの面積の何百もありは個別に参照がチェックされている場合、それは間違いなく多くの時間を消費します、があります。

  加えて、分析が整合スナップショットを確保することができなければならないので、敏感な実行時間の到達可能性分析はまた、GC一時停止に反映されて - 一貫性がここで意味全体にわたって、システム全体の実装でありますある時点で凍結したように見える、オブジェクトの参照関係を常時、分析結果の精度を保証することはできません、ポイントが満たされていない、分析中に変更されることはできません。このリードは、すべてのJavaスレッドがGC上で実行を停止しなければならないとしてもとして知られているCMSコレクタで、重要な理由の一つです(ほとんど)一時停止が発生しない、列挙(Sunは、この事は、「世界の停止」であることを特徴とします)根はまた、一時停止する必要があるとき。

  現在主流のJava仮想マシンは、正確な式GCで、停止するシステムの実装は、すべてチェックされ、グローバル実行コンテキストの基準位置から取り残さする必要はありませんときに、仮想マシンが直接学ぶための方法を持っている必要がありますこれはオブジェクト参照の存在を配置します。ホットスポットを達成するためには、JITコンパイラ、オフセットどのように計算されたデータの種類ロードされたクラスは、オブジェクトがホットスポットに置かれたときに、この目的を達成するためにOopMap呼ばれるデータ構造のセットですスタック及び基準位置を登録する処理は、特定の位置に記録されています。この方法では、GCは、スキャン時には、直接情報を知ることができます。

2.ポイントセキュリティ

OopMapの支援を受けて、ホットスポットは、迅速かつ正確に、完全なGCのルーツ列挙することができますが、非常に現実的な問題が巻き起こっ:各命令ならば、参照関係は変化につながることができ、または非常に多くの命令OopMapの内容の変更対応するOopMapを生成し、それがこのスペースは、高コストのGCになり、余分なスペースの多くを必要とします。

  実際にはホットスポットが実際に唯一の「特別な地位」レコードで、すでに述べたように、各命令OopMapために、この情報を生成していない、問題は(セーフポイント)と呼ばれる、すなわちプログラムの実行ではなく、すべての場所が停止に来ることができますのみ一時停止する安全な地点に到達するために、GCを開始しました。選択したセーフポイントは、どちらもGCが実行時の負荷が過度に上昇することをあまりにも多くの場合、あまりにも長く待つことを可能には小さすぎることはありません。だから、基本的にプログラムが長時間実行するかどうか」の手順の安全ポイントを選択した機能の標準として選択-各命令の実行時間が少なく、非常に短いため、プログラム命令ストリーム長すぎているので、理由長期あまりにも長い間、「長時間実行」最も明白な特徴は、再利用命令のシーケンスです。たとえば、次のメソッド呼び出し、ジャンプ周期、異常ジャンプなど、これらの機能を有する命令は、セーフポイントを生成します。

  セーフポイントのために、考慮すべきもう一つの問題は、(これは実行がJNI呼び出しスレッドは含まれません)どのようにすべてのスレッドでGCはすべて、最寄りの安全な地点に行き、その後、停止に来たときに発生する、2つのオプションがあります。

    1.先制割り込み(先制サスペンション):GCが発生し、セキュリティスレッドのブレークポイントが存在しない場合、それが発見された場合は、最初のすべての混乱のすべてのスレッドの、そしてスレッドを再開し、それはセキュリティのポイントに行きましょう。(ほとんどの仮想ありませんマシンこの方法)

    2.アクティブな割り込み(自主停止):GCは、スレッドを中断する必要がある場合、スレッドは直接単にこのイニシアチブは、実行の各スレッドをポーリングするフラグにフラグを設定し、真の割り込みフラグを発見し、動作しませんが、自分自身がハング中断されました遊びます。投票所及び安全標識点が一致している、プラスどこにオブジェクトを作成する必要は、ローカルメモリを割り当てられました。

今、仮想マシンの主流の方法は、能動的に中断したいGCイベントで使用されています。

3.セキュリティゾーン

セーフポイント以上についてはGCに取得する方法の問題に最適なソリューションを持っているようだが、必ずしもそうではない実際の状況。セーフポイントのメカニズムは、セーフポイントがGCを入力することができ遭遇する時間の短い期間で、プログラムが実行されることを保証します。しかし、プログラムがそれを実行しませんか?行っていない、いわゆるプログラムがCPU時間を割り当てられていない、典型的な例は、スレッドが明らかに、保留中の中断し、スリープ状態や安全な場所にブロックされた状態、JVMのスレッドの割り込み要求に応答でき、この時、「歩く」にすぎJVMではないですスレッドを待ってCPU時間を再割り当てることができます。このケースでは、我々は、セキュリティゾーンに対処する必要があります。

  領域内のセキュリティは、コードフラグメントを指す、参照関係は変化しません。GCは、この領域の任意の場所を開始しても安全です。セキュリティゾーンは、セキュリティの点の延長として見ることができます。

  スレッドは、領域内のコードのセキュリティを実行するJVMは、この時間をGCを開始するときに、全ての第一は、スレッドの安全領域状態として自身を識別し制御しない、セキュア領域に自分自身を識別し、スレッドが安全な領域を残してそれはシステムが列挙ルート(またはプロセス全体のGC)を完了したかどうかを確認するときに完了した場合、それは安全にこれまでのセキュリティゾーンを残すことができ、信号を受信するまで、その後、スレッドは続けて、それ以外の場合は待たなければなりません。


まあ、最もエキサイティングで瞬間の最もコアは、についてですメモリを再利用する方法。この作品の知識ポイントが通常の場所に数回テストしますインタビュアーは、我々が学習に集中する必要があります!

第三に、ガベージコレクションアルゴリズム

1.マーク - スイープアルゴリズム

最も基本的なガベージコレクションアルゴリズム、アルゴリズムは「マーク」と「クリア」2つの段階に分かれています:最初のマークすべてのオブジェクトは、すべてのオブジェクトがマークされて均一なリサイクルマークが完了した後、回復する必要があります。

長所:単純な原理

2つの欠点があります:1、効率、マーキングおよび除去効率は高くありません。2、連​​続したメモリの断片化、大量のプログラムは、より大きな物体が、事前に別のガーベッジコレクション動作をトリガーするために持っていたときにメモリを割り当てるための十分な連続したメモリを見つけることができないために必要がある場合にマークした後、あまりにも多くのスペースデブリにつながることは明らかではありません。

2.コピーしたアルゴリズム

このメモリ上で使用する場合にのみ1が使用する前記利用可能なメモリ容量は同じサイズの2で割って、それはまた、メモリまでの別のブロックにコピーされたオブジェクトを生き、その後、メモリ空間を一掃するために使用されます。

利点:メモリの断片化の問題を解決する能力。

短所:ヒープスペース効率が極めて低い(すべての後に、半分ずつに分け、半分のみ)

3.マーク - 照合アルゴリズム

マークは - アルゴリズムマークをソートする - クリア改善は、アルゴリズムに基づいて行われている、マークフェーズでは、すべてのオブジェクトが完了マークの後にクリーンアップするためにリサイクル可能なオブジェクトに対して直接、リカバリする必要はありません同じマークであるが、全ての生存オブジェクトへのエンド・モバイル、移動中にリサイクル可能なオブジェクトを一掃、このプロセスは、連結と呼ばれています。

長所:メモリは後で仕上げ個別のメモリの断片化の問題を大量に生成しません。

短所:レプリケーション・アルゴリズムは効率が低くなり、オブジェクトのコピー操作のより多くのケースの高い生存率で実行する、オブジェクトの症例の低い生存率のマークの使用 - ソートアルゴリズムの効率が大幅に改善されます。

4.世代コレクションアルゴリズム:

メモリ内のオブジェクトの生存期間に応じて、メモリはいくつかの部分に分割され、Java仮想マシンのメモリは、一般的に、旧世代と新世代に分けて、新世代のメモリ空間の一般的な割り当ては、新しいオブジェクトが作成されたときにときに、新しい世代いくつかはまだ生きているオブジェクトは、旧世代のメモリに移動された後、大規模なオブジェクトが新しい世代に十分な連続したメモリを見つけることができないときも古い世代で直接作成、ガベージコレクタをリサイクル。

世代別ガベージコレクション戦略は、この事実に基づいている:異なるオブジェクトのライフサイクルは同じではありませんそのため、異なるライフサイクルのオブジェクトは、回収効率を向上させるために、異なる回復アルゴリズムを取ることができます。

若い世代(若い世代)

新しく作成されたすべてのオブジェクトの1.最初は、若い世代に配置されます。若い世代の目標は、できるだけ早く、オブジェクトのライフサイクルの短い該当するものを収集することです。

1:エデン領域に1の比率二つ生存(survivor0、survivor1)領域8に従って2.新しい世代のメモリ。エデンエリア二サバイバー領域(一般に)。エデンエリアで発生したほとんどのオブジェクト。オブジェクトの回復におけるファーストエデン生存率はsurvivor0領域にコピーされ、その後、survivor0面積もフルをホストエデン領域に、空に、地区は空になった後、別のsurvivor1の領域にコピーオブジェクトを存続領域とsurvivor0をエデンエデンますsurvivor0領域は、この時間survivor0領域が空の場合、スワップ領域とsurvivor1 survivor0領域、すなわちsurvivor1保持領域が空である、などです。

survivor1ゾーンはオブジェクトエデン生存とsurvivor0を格納するのに十分でない場合3.は、それは古い時代に上に直接置かライブオブジェクトになります。それは新しい世代です全GCをトリガし、古いのフルだ場合は、歳回復してきました

GC 4.新生代もマイナーGC、発生MinorGC比較的高い周波数(必ずしもエデン領域がいっぱいになるので、我々はトリガする必要はない)として知られています

古い世代(旧世代)

1.オブジェクトがゴミのリサイクルはまだ若い世代で生きているの後にN回を経て、古い世代が置かれます。したがって、オブジェクトの長いライフサイクルの一部に格納されている旧世代と考えられています。

2.メモリはまた、新世代よりもはるかに大きい(約比が1:2)トリガー主GC古いのメモリがいっぱいになったとき、つまり、古いターゲットの生存期間が比較的長い、フルGCは、フルGCの発生頻度が比較的低い場合、高い生存マーク。

永久世代(永久世代)

そのようなJavaクラスやメソッドなどの静的ファイルを格納するために使用。永久世代ガーベジコレクションに有意な効果が、一部のアプリケーションでは、この時点で新しいクラスで実行これらのプロセスを保存するために、比較的大きな永久世代のスペースを設定する必要がある、などHibernateは、として、いくつかまたは動的に生成されたクラスを呼び出すことができます。


第四に、ガベージコレクタ

シリアル、PraNew、パラレルスカベンジ:コレクターコレクターの新世代の利用

コレクターの旧コレクターの使用:シリアルオールド、パラレルオールド、CMS

シリアルコレクタ(複製アルゴリズム)

シングルスレッドのコレクター、マークとスイープの新世代は、シンプルかつ効率的なの利点シングルスレッドです。

ParNewコレクタ(ストップ - 複製アルゴリズム) 

コレクターの新世代は、シリアルコレクタのマルチスレッド・バージョンと見なすことができ、それはシリアルマルチコアCPU環境よりも優れた性能を有します。

並列スカベンジコレクタ(ストップ - 複製アルゴリズム)

パラレルコレクタ、高スループットの追求、CPUを効率的に使用します。スループットは、一般的に99%、特定の時間のユーザスレッド= /(ユーザスレッド時間+ GCスレッド時間)です。相互作用に対応するアプリケーション楽屋要求の少ないシーンに適しています。

シリアル・オールド・コレクタ(マーク - 照合アルゴリズム)

古のシングルスレッドコレクターズ・エディションシリアル古いコレクター。

パラレルオールド・コレクタ(ストップ - 複製アルゴリズム)

古い、パラレルコレクタ、スループットの優先度の並列スカベンジコレクタのバージョン

CMS(並行マークスイープ)コレクター(ラベル - クリーニングアルゴリズム)

高並行性、低一時停止、CPU占有率が比較的高い、高回収GC休止時間を選択するために、最短の応答時間を求め、高速応答時間、滞留時間が短い、多核CPUの追求

G1(ガベージ・ファースト)コレクタ(最も洗練されたコレクターの最前線)

地域地域化のガベージコレクタ:最大の利点は、メモリフルスキャンを回避分割されるが、ちょうどすることができ、スキャンする領域を追跡する必要があります。

五、GC執行メカニズム

世代プロセスの目的、したがってガベージコレクションゾーン、ない同じ時間からです。清掃をGCとFull GC:GC 2つのタイプがあります。

スカベンジGC

一般的に、ときに新しいオブジェクトが生成され、エデンの宇宙アプリケーションの障害が発生すると、それは、清掃をGC、エデンのGC面積をトリガー非ライブオブジェクトを削除し、まだサバイバー領域を生き残るために移動物体ます。その後、サバイバーの二つのゾーンを思い付きます。GCエデンゾーンの若い世代のためにこの方法は、古い世代には影響しません。エデン面積が大きい割り当てませんが、オブジェクトのほとんどは、エデン領域の先頭からなので、GCエデン面積が頻繁に発生するので。このように、一般的な使用では、ここで高速、アルゴリズムの高効率を必要とする、エデンはできるだけ早く解放することができるようにします。

フルGC

若い、終身やパーマなど、全体のヒープの並べ替え、。なぜなら清掃をGCよりも遅いので、ヒープ全体を回復するので、可能な限りのフルGCの数を減らす必要がある必要性の完全なGC。JVMを調整する過程で、作業の大部分は、FullGCに調整されます。次の理由は、フルGCにつながることがあります。

1.古い世代(終身の位置)が充填されています

2.永続世代(パーマ)が充填されています

3.System.gc()の呼び出しが表示されます

各ドメインの単一GCヒープの割り当てポリシーの後に4動的な変更


六、JavaのGCは、メモリリークが発生しています

彼らはいつも上のベクトルとして適用されるため、すべてのオブジェクトのオブジェクトは、これらのライフサイクルと静的変数のメモリリーク等のHashMap、ベクターを使用して、一貫性のあるアプリケーションとして表示される可能性が最も高い1.静的なコレクションをリリースすることはできません。

   Static Vector v = new Vector();
   for (int i = 1; i<100; i++) {
        Object o = new Object();
        v.add(o);
        o = null;
   }复制代码

、Vectorオブジェクトコードは、この場合、スタック参照されたオブジェクトのオブジェクト参照とV Oに存在します。Forループでは、我々は、新しいオブジェクトを生成し続け、その後、Vectorオブジェクト、後のO参照空白に追加します。問題は、O参照がGCが発生した場合、我々はそれがGCを回復させることができるかどうかを作成するオブジェクトをオブジェクト、空白行われたときということですか?答えはノーです。GCは、トラッキングコードのスタックで参照するとき、あなたは参照vを見つけ、追跡していきます、なぜなら、あなたがオブジェクトをObjectにVメモリ空間とそこにポイントへの参照があります。参照は空白のままにされているが、他のオブジェクトがまだありますが、それはoをアクセスすることができます参照がオブジェクトなので、GCが解放することができないこと。このサイクルの後に、オブジェクトオブジェクトプログラムは効果がありませんならば、我々は、このJavaプログラムがメモリリークを作成すると信じています。

2.様々な接続、データベース接続、ネットワーク接続は、IO接続がクローズ危機一髪、メモリリークのないGC回復を表示されません。

リスナーの3.リスナーを削除する、該当するリリース対象はありませんが、それはまた、メモリリークにつながることができます。


参考文献:

ブックス:周志明 - 「Java仮想マシン・深さで、」第3章

ブログ:1. Javaのガベージコレクションの深い理解

2. いくつかのガベージコレクションアルゴリズムを使用してJavaのガベージコレクションのメカニズム

3. Javaのインタビューの質問にガベージコレクションメカニズムを取得する記事


おすすめ

転載: juejin.im/post/5d75162ee51d453c12504e78