この記事は機械翻訳のミラー記事です。元の記事にジャンプするにはこちらをクリックしてください。

眺める: 12807|答える: 0

[JavaSE] Javaのガベージコレクションメカニズムを深く理解しましょう

[リンクをコピー]
掲載地 2017/12/04 20:26:51 | | |
1. ごみリサイクル機構の意義  
Java言語の注目すべき特徴は、ガベージコレクション機構の導入であり、これによりC++プログラマにとって最も厄介なメモリ管理の問題を解決し、Javaプログラマーがプログラムを書く際にメモリ管理を考慮する必要がなくなりました。 ガベージコレクションの仕組みにより、Javaのオブジェクトにはもはや「スコープ」という概念はなく、オブジェクトの参照のみが「スコープ」を持っています。ガベージコレクションはメモリリークを効果的に防止し、アイドルメモリを効果的に活用できます。

ps:内存泄露是指该内存空间使用完毕之后未回收,在不涉及复杂数据结构的一般情况下,Java 的内存泄露表现为一个内存对象的生命周期超出了程序需要它的时间长度,我们有时也将其称为“对象游离”。
2. ガベージコレクション機構におけるアルゴリズム  
Java言語仕様はJVMでどのガベージコレクションアルゴリズムを使うかを明示的に指定していませんが、一般的にガベージコレクションアルゴリズムは基本的に2つのことをする必要があります:(1) 不要な情報オブジェクトを見つけること; (2) 不要なオブジェクトが占有しているメモリ空間を取り戻し、プログラムが再びその空間を使えるようにすること。
1. リファレンスカウントコレクタ
1.1 アルゴリズム解析

参照カウントはガベージコレクタの初期戦略です。 このアプローチでは、ヒープ内の各オブジェクトインスタンスに対する参照カウントが存在します。 オブジェクトが作成され、オブジェクトインスタンスが変数に割り当てられると、変数数は1に設定されます。 他の変数がこのオブジェクトへの参照として割り当てられた場合、カウントは1加算されます(a = bの場合、bが参照するオブジェクトインスタンスのカウンターは+1となります)。しかし、オブジェクトインスタンスへの参照が寿命を超えたり新しい値に設定されている場合は、そのオブジェクトインスタンスの参照カウンターを1で差し引きます。 参照カウンターが0のオブジェクトのインスタンスは、ゴミとして収集されることがあります。 オブジェクトインスタンスがガベージコレクションされる場合、参照する任意のオブジェクトインスタンスの参照カウンターはマイナス1となります。
1.2 利点と欠点
価値:

参照カウントコレクタは非常に迅速に実行でき、プログラムの実行に組み込まれています。 プログラムが長時間中断される必要がないリアルタイム環境に有利です。
短所:

循環的な引用は検出できません。 *親オブジェクトが子オブジェクトへの参照を持つ場合、子オブジェクトは親オブジェクトを参照します。 このようにして、引用数が0になることは決してありません。
1.3 参照カウントアルゴリズムは、例えば次のような循環参照問題を解くことはできません。
/** * Java学习交流QQ群:589809992 我们一起学Java! */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;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  
最後の2文はオブジェクト1とオブジェクト2をnullに割り当てており、オブジェクト1とオブジェクト2が指し示すオブジェクトはもはやアクセスできませんが、互いに参照し合っているため参照カウンターは0ではないため、ガベージコレクタはそれらをリサイクルしません。
2. トレーシングコレクターまたはマーク&スイープアルゴリズム
2.1 ルート探索アルゴリズム


ルート探索アルゴリズムは離散数学のグラフ理論から導入され、プログラムはすべての参照関係をグラフとして扱います。GC ROOTノードから出発し、対応する参照ノードを探します。このノードを見つけた後、その参照ノードを探し続けます。すべての参照ノードを探索すると、残りのノードは参照されていないノード、すなわち役に立たないノードとみなされます。
GCルートとして使えるjava
1. 仮想マシンスタックで参照されるオブジェクト(ローカル変数テーブル)
2. メソッド領域の静的属性が参照するオブジェクト
3. メソッド領域における定数が参照するオブジェクト
4. ローカルメソッドスタック内の参照対象オブジェクト(ネイティブオブジェクト)
2.2 トレーシングアルゴリズムの回路図

2.3 マーカークリアリングアルゴリズムの解析

タグパージアルゴリズムはルートコレクションからスキャンし、残ったオブジェクトにマークを付け、上の図のようにタグ付けされていないオブジェクトをリサイクルするために空間全体をスキャンします。 タグパージアルゴリズムはオブジェクトを移動する必要がなく、生存していないオブジェクトのみを処理するため、多くの生存オブジェクトがある場合非常に効率的です。しかし、タグパージアルゴリズムは生き残らないオブジェクトを直接リサイクルするため、メモリ断片化を引き起こします。
3. コンパクト化アルゴリズムまたはラベルフィニッシングアルゴリズム


タグフィニッシュアルゴリズムはタグクリアアルゴリズムと同じ方法でオブジェクトにラベル付けを行いますが、パージング時には異なる。生き残っていないオブジェクトが占有している領域を回復した後、すべての生き残ったオブジェクトを左端の空きスペースに移動し、対応するポインタを更新します。 タグ・フィニッシュアルゴリズムはタグ・パージアルゴリズムに基づいており、オブジェクトを移動するためコストは高くなりますが、メモリ断片化の問題を解決します。 コンパクト化アルゴリズムに基づくコレクタの実装では、一般的にハンドルテーブルとハンドルテーブルが追加されます。
4. コピーアルゴリズム(コンパクトコレクタ)


このアルゴリズムは、ハンドルのオーバーヘッドを克服し、ヒープデブリのガベージコレクションを解決することを提案しています。 オブジェクトが満杯になると、コピーアルゴリズムに基づくガベージコレクションがルート集合からアクティブオブジェクトをスキャンし、各アクティブオブジェクトを自由な面にコピーします(アクティブオブジェクトが占有するメモリの間に空き穴がないように)。これにより、空き面がオブジェクトの面となり、元のオブジェクトの面が空き面となり、プログラムは新しいオブジェクトの面にメモリを割り当てます。 コーピングアルゴリズムに基づく典型的なガベージコレクションはストップ・アンド・コピーアルゴリズムで、ヒープをオブジェクト面と自由領域面に分割し、オブジェクト面と空域面の切り替え時に実行を一時停止します。
5. 世代にわたる収集家


世代ごみリサイクル戦略は、異なる物体のライフサイクルは異なります。 したがって、異なるライフサイクルを持つオブジェクトは異なるリサイクルアルゴリズムを採用し、リサイクル効率を向上させることができます。
ヤングジェネレーション
1. 新たに生成されたすべてのオブジェクトは、まず若い世代に配置されます。 若い世代の目標は、短いライフサイクルのこれらの物をできるだけ早く収集することです。

2. 新世代のメモリは8:1:1の比率で1つのエデン地域と2つの生存者ゾーン(生存者0、生存者1)に分割されています。 エデンゾーンが1つ、サバイバーゾーンが2つ(一般的に)です。 ほとんどのオブジェクトはエデンエリアに出現します。 サバイバー0エリアも満杯の場合、エデンエリアとサバイバー0エリアが別のサバイバー1エリアにコピーされ、その後エデンとサバイバー0エリアが空になり、サバイバー0エリアが空になり、サバイバー0エリアとサバイバー1エリアが交換されます。 つまり、サバイバー1エリアを空にしておくなどです。

3. 生存者1のエリアがエデンと生存者0の生き残ったオブジェクトを保存するには不十分な場合、生き残ったオブジェクトは直接旧時代に保存されます。 もし古い世代も満杯であれば、フルGCが発動し、新世代と古い世代がリサイクルされます

4. 新世代のGCはMinor GCとも呼ばれ、その頻度は比較的高い(エデンエリアが満杯でも必ずしも発動しない)
オールドジェネレーション

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

2. メモリは新世代よりもはるかに大きく(おおよそ1:2)、老年期の記憶が満ちるとメジャーGCが発動し、すなわち完全なGCが起こり、その頻度は比較的低く、老年期対象の生存時間は比較的長く、生存率のマークが高い。
パーマネント・ジェネレーション
Javaクラスやメソッドなどの静的ファイルを保存するために使われます。 永続生成はガベージコレクションに大きな影響を与えませんが、一部のアプリケーションはHibernateなど一部のクラスを動的に生成または呼び出しすることがあり、この場合、実行時にこれらの新しいクラスを格納するために比較的大きな永続生成空間を設定する必要があります。
3. GC(ゴミ収集員)新世代のコレクターが使用するコレクター:シリアル、プラニュー、パラレル・スカベンジ
オールドエイジコレクターが使用するコレクター:シリアルオールド、パラレルオールド、CMS

シリアルコレクタ(レプリケーションアルゴリズム)
新世代のシングルスレッドコレクタ、マーキングおよびクリーニングはシングルスレッドであり、シンプルかつ効率的という利点があります。
シリアルオールドコレクター(ラベル・フィニッシュアルゴリズム)
オールエイジシングルスレッドコレクター、シリアルコレクターのオールエイジバージョン。
ParNew コレクタ(ストップコピーアルゴリズム)
新世代コレクタは、マルチコアCPU環境においてシリアルコレクタよりも性能が優れたシリアルコレクタのマルチスレッド版と見なすことができます。
並列スカベンジコレクタ(ストップコピーアルゴリズム)
高スループットと効率的なCPU利用のための並列コレクタ。 スループットは一般的に99%で、スループット=ユーザースレッド時間 ÷(ユーザースレッド時間+GCスレッド時間)です。 これは、高度な相互作用を必要としないバックグラウンドアプリケーションのようなシナリオに適しています。
パラレルオールドコレクタ(ストップコピーアルゴリズム)
スループット優先性を持つ並列コレクタの古いバージョン
CMS(並行マークスイープ)コレクタ(マーククリーンアルゴリズム)
高並行処理、低一時停止、最短のGC復旧停止時間、高いCPU使用率、高速応答時間、短い一時停止時間、そしてマルチコアCPUによる高応答時間
4. GCの実装メカニズム物は異なる世代で処理されているため、ゴミ収集の場所や時間も異なります。 GCには2種類あります:スカベンジGCとフルGCです。
スカベンジGC
通常、新しいオブジェクトが生成されてエデンのスペースに適用されなかった場合、スカベンジGCが発動し、エデンエリアのGCが発生し、生き残っていないオブジェクトをクリアし、生き残ったオブジェクトをサバイバーエリアに移動します。 そしてサバイバーの2つのゾーンを整理します。 この方法でGCは若い世代のエデン領域に行われ、年長世代には影響しません。 ほとんどの天体はエデン領域から始まり、エデン領域はあまり割り当てられていないため、エデン領域のGCは頻繁に行われます。 したがって、ここでは迅速かつ効率的なアルゴリズムを使って、できるだけ早くエデンを自由にすることが一般的に必要です。
フルGC
ヤング、テニュア、パームを含む山全体を整理してください。 フルGCはScavenge GCよりもヒープ全体を再利用する必要があるため遅いため、フルGCの数はできるだけ減らすべきです。 JVMのチューニングプロセスの大部分はFullGCのチューニングです。 完全なGCは以下の理由で起こり得ます:
1. 終身在職権は正式に書かれています
2. パームはフルと書かれます  
3. System.gc() は通話として表示されます  
4. ヒープのドメイン割り当て戦略は、最後のGC以降に動的に変化します
5. JavaとGCでもメモリリークの問題があります1. HashMapやVectorなどの静的コレクションクラスの使用はメモリリークの起こりやすいものであり、これらの静的変数のライフサイクルはアプリケーションのライフサイクルと同じであり、すべてのオブジェクトを解放することはできません。なぜなら、それらは常にVectorや他によって適用されるからです。
静的ベクトル v = 新しいベクトル(); (int i = 1; i<100; i++) { Object o = new Object();     V.AD(o);     o = 零; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  
この例では、コードスタック内にベクターオブジェクトの参照vとオブジェクトオブジェクトの参照oがあります。 Forループでは、新しいオブジェクトを生成し、ベクターオブジェクトに追加し、o参照を無効化します。 問題は、o参照が無効化されたとき、GCが発生した場合、作成したオブジェクトオブジェクトをGCによってリサイクルできるかどうかです。 答えはノーです。 なぜなら、GCがコードスタック内の参照を追跡するとvの参照を見つけ、さらに追跡していくと、v参照が指し示すメモリ空間内のオブジェクトオブジェクトへの参照があることがわかるからです。 つまり、o参照が空になっていても、オブジェクトオブジェクトへの他の参照がまだアクセス可能であり、GCはそれらを解放できないことを意味します。 このループの後、Objectオブジェクトがプログラムに影響を与えなければ、Javaプログラムにメモリリークがあると仮定します。
2. 各種接続、データベース接続、ネットワーク接続、IO接続などは通話がクローズに近い状態に表示されず、GCによって再利用されないため、メモリリークが発生します。
3. リスナーの使用は、オブジェクトを解放する際にリスナーを削除しない場合、メモリリークを引き起こすこともあります。




先の:初心者はCSSでブラックテクノロジーを少しプレイします
次に:Wanke Cloudのスナップソフトウェアウイルストロイの木馬にご注意ください!
免責事項:
Code Farmer Networkが発行するすべてのソフトウェア、プログラミング資料、記事は学習および研究目的のみを目的としています。 上記の内容は商業的または違法な目的で使用されてはならず、そうでなければ利用者はすべての結果を負うことになります。 このサイトの情報はインターネットからのものであり、著作権紛争はこのサイトとは関係ありません。 ダウンロード後24時間以内に上記の内容を完全にパソコンから削除してください。 もしこのプログラムを気に入ったら、正規のソフトウェアを支持し、登録を購入し、より良い本物のサービスを受けてください。 もし侵害があれば、メールでご連絡ください。

Mail To:help@itsvse.com