Javaのゴミ回収メカニズム


一:誰がGarbage Collectionをしていますか.    一つの流行の言い方:C++の中で、システムはごみの回収をしています;Javaでは、Java自身がやっています.
    C++では、メモリの解放は手動で処理され、delete演算子で割り当てられたメモリを解放します.これは流行の言い方です.正確には、アプリケーションがエンティティを必要としないと判断した場合、deleteでシステムにこの空間を回収できることを伝える必要があります.この要求は、符号化者にとって、面倒で難しいことです.どのBBSに行っても、C/C++ブロックにはメモリの漏洩に関する話題がたくさんあります.
    Javaは1種の異なっていて、とても便利な方法を採用します:Garbage Collection.ごみの回収のメカニズムはJVMの中に置きます.JVMは完全にゴミ回収を担当しており、アプリケーションは必要に応じてスペースを申請するだけで、対象を捨てるときにスペース回収の問題に関心を持つ必要はありません.
    相手はいつ捨てられますか.
    C++では,オブジェクトがその役割ドメインから離れると,そのオブジェクトは破棄される.
    オブジェクトのライフサイクルは、その役割ドメインに関係なく、参照にのみ関係しません.
    Javaのゴミ回収メカニズムには一般的に10種類近くのアルゴリズムが含まれている.これらのアルゴリズムの多くに対して,我々は関心を持つ必要はない.最も簡単なのは、符号化に関連する参照カウント法だけです.
    1つのオブジェクトで、1つ以上の参照変数がそれを指すことができます.オブジェクトに参照変数が指定されなくなった場合、このオブジェクトは適用されません.あるいは、この対象はごみ回収メカニズムで回収することができます.
    つまり、あるオブジェクトへの参照が存在しない場合、アプリケーションはJVMに「私はこのオブジェクトを必要としない.回収できる」と伝えることを意味します.
    JVMのゴミ回収メカニズムはスタック空間をリアルタイムで検出する.オブジェクトの参照数が0であることが判明すると、そのオブジェクトは回収対象リストに登録されます.しかし、すぐに廃棄するわけではない.
   三:捨てると回収される?
    このオブジェクトは存在する必要がないと認定され、使用するメモリは解放されます.回収されたメモリは、後続の再割り当てに使用できます.
    しかし、対象が捨てられた直後に回収されたわけではない.JVMプロセスの空間回収には大きなシステムオーバーヘッドがあります.アプリケーション・プロセスがオブジェクトを破棄するたびに、その空間をすぐに回収すると、システム全体の稼働効率が非常に低下するに違いありません.
    前述したように,JVMのゴミ回収メカニズムには複数のアルゴリズムがある.参照カウント法は、オブジェクトが捨てられたかどうかを判断するために用いられるほか、いつ回収されるか、どのように回収されるかを決定するために用いられる.JVMのゴミ回収メカニズムは時間と空間のバランスをとる.
    従って、システム効率を向上させるために、ゴミ回収器は、通常、2つの条件を満たす場合にのみ動作する.すなわち、オブジェクトが回収され、システムが回収する必要がある.ごみの回収に時間がかかることを忘れないでください.そのため、Javaランタイムシステムは必要なときだけ使用します.そのため、ごみの回収が発生する正確な時間を知ることはできません.
   四:参照変数がないオブジェクトは役に立ちますか?
    前述したように、参照変数を掛けていないオブジェクトは適用されて廃棄されます.これは、スタック空間でゴミであり、いつでもJVMに回収される可能性があることを意味します.
    しかし、ここには例外ではない例外があります.一度に使用するオブジェクト(一時オブジェクトと呼ばれる本もあります)については、変数を参照せずに指定できます.最も簡単でよく見られる例を挙げます.
    System.out.println(“I am Java!”);
    文字列オブジェクトを作成してprintln()に直接渡す方法です.
    五:応用はごみ回収に関与できますか.
    多くの人がJavaのゴミ回収に不安を感じ、アプリケーションコードでJVMのゴミ回収動作を制御したいと考えています.これはあり得ないことだ.ごみ回収メカニズムでは、JVMにメッセージを送信する方法は2つしかありません.1つ目は、あるオブジェクトを指すすべての参照変数をすべて移動することです.これは、このオブジェクトが不要であるというメッセージをJVMに送信することに相当します.2つ目は呼び出しライブラリメソッドSystem.gc()で、多くの本ではJavaをゴミ回収に呼び出すと言われています.
    1つ目は通知であり,System.gc()を呼び出すのも1つの要求にすぎない.JVMはこのメッセージを受け取った後、すぐにゴミ回収をするのではなく、いくつかのゴミ回収アルゴリズムに重み付けをして、ゴミ回収操作を容易にしたり、早めに発生したり、回収したりしただけです.
    JVMが直ちにごみを回収することを望んで、1種の需要です.実は、ある時間内にごみを回収しないほうがいいという反対のニーズがあります.実行速度が最も速いリアルタイムシステム、特に組み込みシステムが要求される場合、このようなことが望ましいことが多い.
    Javaのゴミ回収メカニズムは、特定のプロセスにサービスするのではなく、すべてのJavaアプリケーションプロセスにサービスします.そのため、どのプロセスもゴミ回収機に何をするか、どうするか、どれだけするかを命令することはできません.
    六:対象が回収されたときにすること
    1つのオブジェクトが実行されている間に、関連するものがある可能性があります.したがって、オブジェクトが破棄される直前に、いくつかの善後作業が必要になる場合があります.これらの操作はfinalize()メソッド(ターミネータと呼ばれることが多い)に書くことができます.
    protected void finalize()

    {

    // finalization code here

    }

    この終端器の用途はC++の構造関数に似ており,いずれも自動呼び出しである.しかし,両者の呼び出しタイミングが異なり,両者の表現行為に大きな違いがある.C++の構造関数は、常にオブジェクトが役割ドメインから離れたときに呼び出されます.すなわち,C++解析関数の呼び出しタイミングは決定され,適用可能に判別される.しかし,Javaターミネータはオブジェクトが破棄されたときである.以上から分かるように,破棄されたオブジェクトがいつ破棄されるかは,アプリケーションでは知ることができない.また、ほとんどの場合、破棄されたオブジェクトは適用終了後も破棄されない.
    符号化の際、この点を考慮する.たとえば、あるオブジェクトが動作中にファイルを開き、オブジェクトが破棄されたときに閉じないで、ファイルを閉じる文を終端器に書きます.これにより、ファイル操作に問題が発生します.ファイルが排他的に開いている場合、他のオブジェクトはこのファイルにアクセスできません.ファイルが共有で開かれている場合、別のファイルにアクセスしたオブジェクトは、アプリケーションが終了するまで、破棄されたオブジェクトがファイルに書き込まれた新しい内容を読むことができません.
    少なくともファイル操作の場合、符号化者はJava終端器とC++構造関数の違いを認識しなければならない.
    では、アプリケーションが終了すると、アプリケーション内のすべてのfinalize()が実行されますか?Bruce EckelのThinking in Javaによると、「プログラムが終了するまで、すべてのエンドモジュールが呼び出されるわけではない」という.これは、正常終了を適用した場合、非正常終了を指すだけですか?
    そのため、どのような仕上げ操作がfinalize()に入るかは、酒を飲む必要があります.