プログラムがオブジェクト、配列などの参照タイプのエンティティを作成すると、システムはヒープメモリ内のオブジェクトのメモリの一部を割り当て、オブジェクトはこのメモリに保存されます。このメモリが参照変数によって参照されなくなった場合、メモリの部分はごみになり、ガベージコレクションメカニズムがリサイクルされるのを待ちます。ごみ収集メカニズムには3つの特性があります。
ガベージ収集メカニズムは、ヒープメモリ内のオブジェクトのリサイクルのみを担当し、物理リソース(データベース接続、オープンファイルリソースなど)をリサイクルすることはなく、オブジェクトを作成する方法以外の方法でオブジェクトに割り当てられたメモリにリサイクルすることもありません(ローカル方法でMallocを呼び出すオブジェクトによって適用されるメモリなど)
このプログラムは、ガベージコレクションの操作を正確に制御できないため、ゴミコレクションのみをお勧めします。 2つの推奨方法があります。System.gc()とruntime.getRuntime()。gc()
ガベージコレクションの前に、そのfinalize()メソッドは常に最初に呼び出されますが、それはガベージコレクション時間と同じであり、firemize()メソッドも確かではありません。
上記の3つの特性に関しては、3つの問題があります。
1.クリーニング作業は、オブジェクトを作成する方法以外に割り当てられたメモリやその他の物理リソースを解放するために手動で行う必要があります。期限切れのオブジェクト参照を排除するように注意してください。そうしないと、OOMが発生する可能性があります。
手動のクリーニングは通常、試してみるようなコード構造を使用します...最終的に...
例は次のとおりです。
Import java.io.fileinputStream; Import java.io.fileNotFoundException; Import java.io.ioexception; public class manualclear {public static void main(string [] args){fileinputStream fileinputStream = null; try {fileInputStream = new fileInputStream( "./ src/manualclear.java"); } catch(filenotfoundexception e){system.out.println(e.getmessage()); e.printstacktrace();戻る; } try {byte [] bbuf = new byte [1024]; int hasread = 0; try {while((hasread = fileinputStream.read(bbuf))> 0){system.out.println(new String(bbuf、0、hasread)); }} catch(ioexception e){e.printstacktrace(); }}最後に{try {fileInputStream.close(); } catch(ioexception e){e.printstacktrace(); }}}}通常、期限切れのオブジェクトへの参照によって引き起こされる3つの一般的なOOMケースがあります。これらの3つのケースは通常、検出が容易ではなく、短期間で実行される問題はありません。ただし、長い間、漏れたオブジェクトの数が最終的にプログラムをクラッシュさせます。
クラスが単独でメモリを管理する場合、次のようにメモリリークに注意する必要があります。
Import Java.util.arrays; Import Java.util.emptystackexception; class stack {private object [] elements;プライベートINTサイズ。 Private Static Final int default_inital_capacity = 16; public stack(){Elements = new Object [default_inital_capacity]; } public void push(object e){ensurecapacity();要素[size ++] = e; } public object pop(){if(size == 0){throw new emptystackexception(); } return elements [ - size]; } private void ensurecapacity(){if(elements.length == size){elemention = arrays.copyof(elements、2 * size + 1); }}} public class stackdemo {public static void main(string [] args){stack stack = new stack(); for(int i = 0; i <10000; i ++){stack.push(new object()); } for(int i = 0; i <10000; i ++){stack.pop(); }}}メモリリークの理由は、スタック上の他のオブジェクトがもはや参照されなくても、スタッククラスの要素[]配列がこれらのオブジェクトへの参照を保持しているため、オブジェクトがガベージコレクションによってリサイクルされないことです。したがって、クラスがメモリを単独で管理する必要がある場合、内部的に維持されているこれらの期限切れの参照が時間内に参照されるかどうかに注意してください。この例では、スタックがリリースされた後にのみ、表示されたものが表示されます。
要素[size] = null;
キャッシュは、メモリリークに警戒することです。この状況は、通常、オブジェクトがキャッシュに入れられると、長い間使用されていない場合は忘れがちな可能性があります。通常、Wakehashmapを使用してキャッシュを表すことができます。キャッシュ内のアイテムが期限切れになった後、自動的に削除できます。または、背景スレッドで定期的に実行して、バッファ内の期限切れのアイテムをクリアすることもできます。
リスナーまたはコールバックの登録は、登録解除に最適です。
2。finalize()を手動で呼び出さないでください、それはゴミコレクターに呼び出されます
3.オブジェクトが適切にクリーニングされていないことを確認するために、最終条件を判断するために使用されない限り、finalize()メソッドを使用しないでください。手動でクリーンアップしたときに、システムリソースをクリーンアップするためのセキュリティネットワークとして使用されます。遅延した洗浄を掃除する必要はありません。忘れられたクリーニングリソースに関する情報を同時に記録すると、エラーが後で発見され、忘れられたクリーニングコードを時間内に変更するのにも便利です。オブジェクト内のローカルメソッドによって取得された、非常に重要でないシステムリソースを解放します。
finalize()メソッドは正確に保証されていないため、主要なリソースをリリースしないことが最善ですが、上記の3つのケースで使用できます。最初のケースは次のとおりです。
クラスブック{boolean checkout = false;パブリックブック(ブールチェックアウト){this.checkout = checkout; } public void checkin(){checkout = false; } @Override Protected void finalize()throws throws throwable {if(checkout){system.out.println( "error:check out"); }}} public class finalizecheckobjectuse {public static void main(string [] args){new book(true); System.gc(); }}実行結果:
エラー:チェックしてください
例の本のオブジェクトは、リリースする前にチェックイン状態にある必要があります。そうしないと、リリースできません。ファイナライズの実装は、時間内に違法なオブジェクトを発見するのに役立ちます。より直接的に、参照変数を使用してファイナライズで直接参照して、到達可能な状態に再び入り、再び処理できるようにします。
別の注意点は、サブクラスが親クラスのファイナライズ方法を無効にしているが、スーパーを手動で呼び出すことを忘れる場合、またはサブクラスのファイナライズプロセスに例外があるため、super.finalizeが実行されない場合、親クラスの最終メソッドは呼び出されません。
次のように:
class parent {@Override Protected void finalize()throws throws throws {system.out.println(getclass()。getname() + "finalize start"); }} class Son extends parent {@Override Protected void finalize()throws throws {system.out.println(getClass()。getName() + "finalize start"); }} public class superfinalizelost {public static void main(string [] args){new Son(); System.gc(); }}実行結果:
息子はスタートを完成させます
または
class parent {@Override Protected void finalize()throws throws throws {system.out.println(getclass()。getname() + "finalize start"); }} class Son extends parent {@Override Protected void finalize()throws throws {system.out.println(getClass()。getName() + "finalize start"); int i = 5/0; super.finalize(); }} public class superfinalizelost {public static void main(string [] args){new Son(); System.gc(); }}実行結果:
息子はスタートを完成させます
2番目のケースでは、try ...最後に...構造を解決するために使用できますが、最初のケースでは、End Method Guardianと呼ばれるメソッドを使用することをお勧めします。例は次のとおりです
class parent2 {private final object finalizeguardian = new object(){protected void finalize()throws throws {system.out.println( "ここで親クラス終了方法でロジックを実行する"); }; };} class son2 extends parent2 {@override保護されたvoid finalize()throws throws throws {system.out.println(getClass()。getName() + "finalize start"); int i = 5/0; super.finalize(); }} public class finalizeguardian {public static void main(string [] args){new Son2(); System.gc(); }}実行結果:
ここで親クラス終了方法でロジックを実行する
Son2は開始を完了します
これにより、親クラスの最終方法で必要な操作が実行されます。
上記はこの記事に関するものです。すべての人の学習に役立つことを願っています。