序文
セグメントフォーに質問を見ました。Javaには完全なGCメカニズムがあるため、Javaにメモリリークの問題が発生し、メモリリークのケースを提供できます。この質問ビューは、この質問に対する完全な答えを提供します。
ゴミリサイクルメカニズムの紹介
実行中のプログラム中に、各オブジェクトが作成され、オブジェクトデータを保存するために一定量のメモリが割り当てられます。メモリを割り当て続けるだけで、プログラムは遅かれ早かれメモリが不十分であるという問題に直面します。したがって、どの言語でも、メモリを再利用できるように、期限切れのオブジェクトのメモリを解放するメモリ回復メカニズムがあります。
メモリリサイクルメカニズムは、実装の役割に応じて2つのタイプに分けることができます。 1つは、プログラマーがメモリ(C言語など)のリリースを手動で実現し、もう1つはこの記事で紹介するJava Garbage Collectionメカニズムなど、言語の組み込みメモリリサイクルメカニズムです。
Javaのごみ収集メカニズム
プログラムのランタイム環境では、Java Virtual Machineは、参照を失ったオブジェクトで占められているメモリを再生することを担当するシステムレベルのガベージコレクション(GC、Carbage Collection)スレッドを提供します。 GCを理解するための前提条件は、ゴミ収集に関連するいくつかの概念を理解することです。これらの概念は、以下で1つずつ導入されます。
JVMヒープ領域のオブジェクトの状態
Javaオブジェクトのインスタンスは、JVMのヒープエリアに保存されます。 GCスレッドの場合、これらのオブジェクトには3つの状態があります。
1。タッチ可能な状態:プログラムにはさまざまな参照があるため、このオブジェクトはタッチ可能な状態です。
2。再活性化状態:プログラム内の変数がこのオブジェクトを参照していない場合、オブジェクトは触れられる状態から再活性化状態に変更されます。 CGスレッドは、特定の時間にこのオブジェクトのファイナライズメソッドを呼び出す準備をします(ファイナライズメソッドは、子オブジェクトを継承または書き換えます)。ファイナライズメソッドのコードは、オブジェクトをタッチ可能な状態に変換する場合があります。そうしないと、オブジェクトは触れられない状態に変換されます。
3。手に負えない状態:GCスレッドは、オブジェクトが触れられない状態にある場合にのみ、このオブジェクトのメモリをリサイクルできます。
オブジェクトを正しくリリースするには、GCはアプリケーション、引用、引用、割り当てなどを含む各オブジェクトの実行ステータスを監視する必要があります。GCはそれを監視する必要があるため、GCはオブジェクトが上記の状態にあるかどうかに関係なく知ります。
上記のように、GCスレッドは、特定の時間に復活可能な状態オブジェクトのファイナライズ方法を実行します。では、いつ実行されますか?異なるJVM実装者は異なるアルゴリズムを使用してGCを管理する場合があるため、開発者はいつでも、さまざまな操作を実行するGCスレッドのタイミングを予測することはできません(オブジェクト状態の検出、オブジェクトメモリの解放、オブジェクトの呼び出しの最終メソッドを含む)。 GCスレッドは、System.gc()およびruntime.gc()関数を介してできるだけ早くガベージコレクション操作を実行するように思い出させることができますが、GCスレッドが対応するリサイクル操作をすぐに実行することを保証することはできません。
メモリリーク
メモリリークは、プログラムが使用されなくなったメモリをリリースできないため、リソースの無駄をもたらす間違った設計によって引き起こされます。 GCは、参照を失ったオブジェクトで占められたメモリを自動的にクリーンアップします。ただし、プログラミングエラーのために一部のオブジェクトが常に参照される場合、メモリリークが発生します。
たとえば、次の例。アレイは、スタックエントリとスタック出口の2つの操作を備えたスタックを実装するために使用されます。
com.sun.javafx.collections.elementobservablelistdecorator; Import com.sun.swing.internal.plaf.metal.resources.metal_sv; Import java.beans.exceptionListener; import java.util.emptystackexception; */public class mystack {private object [] elements; Private int increment = 10;プライベートINTサイズ= 0; public Mystack(int size){Elements = new Object [size]; } // Stack public void push(object o){capiought();要素[size ++] = o; } //スタックパブリックオブジェクトpop(){if(size == 0)throw new emptystackexception();返品要素[ - サイズ]; } //スタックプライベートボイド容量の容量を増やす{){if(elements.length!= size)return; object [] newArray = new Object [Elements.Length + Increment]; System.ArrayCopy(Elements、0、NewArray、0、Size); } public static void main(string [] args){mystack stack = new Mystack(100); for(int i = 0; i <100; i ++)stack.push(new Integer(i)); for(int i = 0; i <100; i ++){system.out.println(stack.pop()。toString()); }}}このプログラムは利用可能で、一般的なスタックエントリとスタックエントリ操作をサポートします。ただし、適切に処理されていない問題があります。つまり、スタック操作がリリースされると、配列のスタック要素への参照がリリースされないため、プログラムはこのオブジェクトへの参照を維持します(このオブジェクトは配列によって参照されます)。 GCは常にこのオブジェクトにアクセス可能であると考えています。つまり、メモリのリリースについて話す必要はありません。これは、メモリリークの典型的なケースです。このため、変更されたコードは次のとおりです。
// public Object pop(){if(size == 0)throw new emptystackexception();オブジェクトo =要素[ - サイズ];要素[size] = null; oを返します。 }上記の記事には、Java Garbage Collectionメカニズムとメモリリークを深く理解しています。これは私があなたと共有したすべてのコンテンツです。私はそれがあなたに参照を与えることができることを願っています、そしてあなたがwulin.comをもっとサポートできることを願っています。