finalize()メソッドはいつJavaで呼び出されますか?


330

finalize()メソッドがでいつ呼び出されるかを知る必要がありJVMます。finalize()メソッドをオーバーライドして呼び出されたときにファイルに書き込むテストクラスを作成しました。実行されません。実行されない理由を誰かに教えてもらえますか?


34
補足として:finalizeはJava 9で非推奨としてマークされています
Reg


オブジェクトまたはクラスへの参照がある場合。finalize()ガベージコレクションは影響を与えません。
ha9u63ar

回答:


273

一般にfinalize()、クリーンアップなどに頼らないことが最善です。

よると、Javadocの(それは読書価値があるだろう)、それは次のようになります。

オブジェクトへの参照がなくなったとガベージコレクションが判断したときに、オブジェクトのガベージコレクターによって呼び出されます。

Joachimが指摘したように、オブジェクトが常にアクセス可能である場合、これはプログラムの存続期間中に決して発生しない可能性があります。

また、ガベージコレクターが特定の時間に実行されることは保証されていません。一般的に、私が言おうとしていることfinalize()は、必要な特定の方法がない限り、おそらく一般的に使用する最良の方法ではありません。


19
つまり、(将来の読者のために明確にするために)メインクラスで呼び出されることはありません。メインクラスが閉じるときに、ガベージを収集する必要がないからです。OSは、とにかくアプリが使用したすべてのものをクリーンアップします。
マークジェロニムス

113
「使用するのに最適な方法ではありません...何か必要なものがない限り」-その文はすべての100%に当てはまるので、役に立ちません。ヨアヒムザウアーの答えははるかに優れています
BT

1
@ Zom-Bあなたの例は明確にするのに役立ちますが、理解を深めるために、おそらくメインクラスがデーモン以外のスレッドを作成して戻ってきた場合、メインクラスで呼び出される可能性がありますか?
トムG

3
では、どのfinalizeような場合に役立つでしょうか?
nbro

3
@MarkJeronimus-実際には、それは無関係です。finalize()クラスのインスタンスは>> <<ごみがない場合、メインメソッドが終了収集されたときに、メインクラスの上のメソッドが呼び出されます。さらに、メインクラス、アプリケーションが完了する前にガベージコレクションされる可能性があります。たとえば、「メイン」スレッドが他のスレッドを作成してから戻るマルチスレッドアプリでは。(実際には、非標準のクラスローダーが必要になります...)
Stephen C

379

このfinalizeメソッドは、オブジェクトがガベージコレクションを実行しようとするときに呼び出されます。これは、ガベージコレクションの対象になった後であればいつでも可能です。

オブジェクトがガベージコレクションされない(したがって、finalize呼び出されない)可能性は完全にあることに注意してください。これは、オブジェクトがgcに適格にならない場合(JVMの全存続期間を通じて到達可能であるため)、またはオブジェクトが適格になった時点からJVMの実行が停止する時点までの間に実際にガベージコレクションが実行されない場合に発生します(これは多くの場合、テストプログラム)。

finalizeまだ呼び出されていないオブジェクトで実行するようにJVMに指示する方法はいくつかありますが、それらを使用することもお勧めできません(そのメソッドの保証はあまり強くありません)。

finalizeアプリケーションの正しい操作に依存している場合は、何か問題があります。finalizeなければならないだけで(通常は非Java)リソースのクリーンアップのために使用されます。そしてそれはまさに、JVMがfinalizeオブジェクトで呼び出されることを保証しないためです。


2
@Rajesh。いいえ、それは「寿命」の問題ではありません。プログラムを無限ループ(何年も)に置くことができ、ガベージコレクターが必要ない場合は実行されません。
ChrisCantrell 2013

5
@VikasVerma:完璧な置き換えは何もありません:あなたはそれらを必要とすべきではありません。それが意味を持つ唯一のケースは、クラスが外部リソース(TCP / IP接続、ファイルなど、Java GCが処理できないもの)を管理する場合です。そのような場合、Closableおそらくインターフェース(およびその背後にあるアイデア)が必要です。.close()リソースを閉じる/破棄し、クラスのユーザーが適切なタイミングで呼び出すように要求します。あなたは可能性がある追加したいfinalize「だけ保存する」方法を、しかし、(それが信頼性の高い十分ではありませんので)それは、より多くのデバッグツールの実際の修正よりもだろう。
Joachim Sauer

4
@Dragonborn:これは実際にはかなり異なる質問であり、個別に質問する必要があります。シャットダウンフックはありますが、JVMが予期せずシャットダウンした(クラッシュした)場合は保証されません。しかし、それらの保証はファイナライザの保証よりもはるかに強力です(そしてそれらは同様に安全です)。
Joachim Sauer

4
最後の段落では、呼び出される保証はありませんが、リソースをクリーンアップするためにのみ使用するように言っています。この楽観主義は語っていますか?これはリソースのクリーンアップにも適していないため、信頼性の低いものだと思います。
Jeroen Vannevel

2
ファイナライザは時々その日を節約することができます...私はサードパーティのライブラリがFileInputStreamを使用していて、決して閉じない場合がありました。私のコードはライブラリのコードを呼び出していて、ファイルを移動しようとしましたが、まだ開いているため失敗しました。System.gc()FileInputStream :: finalize()を呼び出すために呼び出しを強制する必要があり、それからファイルを移動することができました。
Elist

73
protected void finalize() throws Throwable {}
  • すべてのクラスfinalize()はjava.lang.Objectからメソッドを継承します
  • このメソッドは、オブジェクトへの参照が存在しないと判断したときにガベージコレクターによって呼び出されます
  • Object finalizeメソッドはアクションを実行しませんが、どのクラスによってもオーバーライドされる可能性があります
  • 通常は、Java以外のリソースをクリーンアップするためにオーバーライドする必要があります(ファイルを閉じるなど)
  • オーバーライドするfinalize()場合は、try-catch-finallyステートメントを使用して常にを呼び出すことをお勧めしますsuper.finalize()。これは、クラスを呼び出すオブジェクトが使用するリソースを誤って閉じないようにするための安全対策です。

    protected void finalize() throws Throwable {
         try {
             close();        // close open files
         } finally {
             super.finalize();
         }
     }
  • finalize()ガベージコレクション中にスローされた例外はファイナライズを停止しますが、それ以外の場合は無視されます

  • finalize() どのオブジェクトでも2回以上実行されることはありません

引用元:http : //www.janeg.ca/scjp/gc/finalize.html

この記事をチェックすることもできます:


25
リンクしているJavaWorldの記事は1998年のものであり、特にアドバイスとして、1つのSystem.runFinalizersOnExit()を呼び出して、JVMが終了する前にファイナライザが実行されるようにするという提案があります。このメソッドは現在非推奨であり、コメント「このメソッドは本質的に安全ではありません。他のスレッドがそれらのオブジェクトを同時に操作している間に、ライブオブジェクトでファイナライザーが呼び出され、不安定な動作またはデッドロックが発生する可能性があります。だから私はそれをしません。
Greg Chabala

3
runFinalizerOnExit()はスレッドセーフではないため、実行できるのはRuntime.getRuntime()。addShutdownHook(new Thread(){public void run(){destroyMyEnclosingClass();}});です。クラスのコンストラクタで。
Ustaman Sangat 2012

2
@Ustaman Sangatこれはその方法ですが、shutdownHookからインスタンスへの参照を設定することを覚えておいてください。これにより、クラスがガベージコレクションされないことがほぼ保証されます。つまり、メモリリークです。
pieroxy 2013年

1
@pieroxy、私はここでfinalize()を何も使用しないことに関して他の全員に同意しますが、シャットダウンフックからの参照が必要になる理由はわかりません。ソフトリファレンスを持つことができます。
Ustaman Sangat 2013

25

Java finalize()メソッドはデストラクタではないため、アプリケーションが依存するロジックの処理には使用しないでください。Java仕様finalizeでは、アプリケーションのライブタイム中にメソッドが呼び出されることは保証されていません。

あなたがおそらく望んでいるのは、以下のようなfinallyとクリーンアップ方法の組み合わせです。

MyClass myObj;

try {
    myObj = new MyClass();

    // ...
} finally {

    if (null != myObj) {
        myObj.cleanup();
    }
}

20

効果的なJava、第2版のページ27を確認して ください。項目7:ファイナライザを使用しない

ファイナライザは予測不可能で、多くの場合危険であり、一般に不要です。ファイナライザでタイムクリティカルなことは絶対に行わないでください。重要な永続状態を更新するためにファイナライザに依存することはありません。

リソースを終了するには、代わりにtry-finallyを使用します。

// try-finally block guarantees execution of termination method
Foo foo = new Foo(...);
try {
    // Do what must be done with foo
    ...
} finally {
    foo.terminate(); // Explicit termination method
}

3
または、try-with-resourcesを使用する
ガブリエルガルシア

3
これは、オブジェクトの存続期間が1つの関数のスコープ内にあると想定しています。もちろん、これはOPが参照しているケースではなく、基本的に誰もが必要としているケースではありません。「キャッシュエンジンの戻り値の参照カウント」を考えてください。最後の参照が解放されたときにキャッシュエントリを解放したいが、最後の参照が解放された時期がわからない。finalize()は、たとえば、参照カウントをデクリメントできますが、ユーザーが明示的にfree関数を呼び出す必要がある場合は、メモリリークを要求しています。通常、私は両方を実行します(リリース機能+ファイナライズのダブルチェック...)...
Erik Aronesty

16

finalize()メソッドはいつJavaで呼び出されますか?

finalizeメソッドは、GCがオブジェクトに到達できなくなったことを検出した後、オブジェクトが使用するメモリを実際に再利用する前に呼び出されます。

  • オブジェクトが到達不能にならない場合、そのオブジェクトfinalize()が呼び出されることはありません。

  • GCが実行されない場合、finalize()呼び出されることはありません。(通常、GCは、JVMがそれを価値のあるものにするのに十分なガベージがあると判断した場合にのみ実行されます。)

  • 特定のオブジェクトに到達できないとGCが判断するまでに、複数のGCサイクルが必要になる場合があります。(Java GCは通常「世代別」コレクターです...)

  • GCは、オブジェクトが到達不能でファイナライズ可能であることを検出すると、ファイナライズキューに配置されます。ファイナライズは通常、通常のGCと非同期で行われます。

(JVM仕様で、JVM がファイナライザを実行することは実際に許可されていません...オブジェクトが使用するスペースを再利用しない場合。 。)

結論としては、決まった時間枠で行わなければならないことを行うためにファイナライズに依存することは賢明ではないということです。まったく使用しないことが「ベストプラクティス」です。finalize()メソッドで実行しようとしていることを何でも実行するためのより良い(つまり、より信頼できる)方法があるはずです。

ファイナライズの唯一の正当な用途は、アプリケーションコードによって失われたオブジェクトに関連付けられたリソースをクリーンアップすることです。それでも、そもそもオブジェクトを失わないようにアプリケーションコードを作成する必要があります。(たとえば、Java 7以降のtry-with-resourcesを使用しclose()て、常に呼び出されるようにします...)


ファイルを上書きしてfinalize()メソッドが呼び出されたときにファイルに書き込むテストクラスを作成しました。実行されません。実行されない理由を誰かに教えてもらえますか?

言うのは難しいですが、いくつかの可能性があります:

  • まだ到達可能であるため、オブジェクトはガベージコレクションされません。
  • テストが完了する前にGCが実行されないため、オブジェクトはガベージコレクションされません。
  • オブジェクトはGCによって検出され、GCによってファイナライズキューに配置されますが、テストが完了する前にファイナライズは完了していません。

10

JVMによるfinalize()メソッドの呼び出しには不確実性があるため(オーバーライドされたfinalize()が実行されるかどうかがわからない)、調査目的でfinalize()が呼び出されたときに何が起こるかを観察するより良い方法は、 JVMがコマンドでガベージコレクションを呼び出すように強制しますSystem.gc()

具体的には、オブジェクトが使用されなくなったときにfinalize()が呼び出されます。しかし、新しいオブジェクトを作成してそれを呼び出そうとすると、その呼び出しの確実性はありません。したがって、確実に将来明らかに使用されないnullオブジェクトを作成するため、オブジェクトのfinalize呼び出しcを確認cします。

class Car {

    int maxspeed;

    Car() {
        maxspeed = 70;
    }

    protected void finalize() {

    // Originally finalize method does nothing, but here we override finalize() saying it to print some stmt
    // Calling of finalize is uncertain. Difficult to observe so we force JVM to call it by System.gc(); GarbageCollection

        System.out.println("Called finalize method in class Car...");
    }
}

class Bike {

    int maxspeed;

    Bike() {
        maxspeed = 50;
    }

    protected void finalize() {
        System.out.println("Called finalize method in class Bike...");
    }
}

class Example {

    public static void main(String args[]) {
        Car c = new Car();
        c = null;    // if c weren`t null JVM wouldn't be certain it's cleared or not, null means has no future use or no longer in use hence clears it
        Bike b = new Bike();
        System.gc();    // should clear c, but not b
        for (b.maxspeed = 1; b.maxspeed <= 70; b.maxspeed++) {
            System.out.print("\t" + b.maxspeed);
            if (b.maxspeed > 50) {
                System.out.println("Over Speed. Pls slow down.");
            }
        }
    }
}

出力

    Called finalize method in class Car...
            1       2       3       4       5       6       7       8       9
    10      11      12      13      14      15      16      17      18      19
    20      21      22      23      24      25      26      27      28      29
    30      31      32      33      34      35      36      37      38      39
    40      41      42      43      44      45      46      47      48      49
    50      51Over Speed. Pls slow down.
            52Over Speed. Pls slow down.
            53Over Speed. Pls slow down.
            54Over Speed. Pls slow down.
            55Over Speed. Pls slow down.
            56Over Speed. Pls slow down.
            57Over Speed. Pls slow down.
            58Over Speed. Pls slow down. 
            59Over Speed. Pls slow down.
            60Over Speed. Pls slow down.
            61Over Speed. Pls slow down.
            62Over Speed. Pls slow down.
            63Over Speed. Pls slow down.
            64Over Speed. Pls slow down.
            65Over Speed. Pls slow down.
            66Over Speed. Pls slow down.
            67Over Speed. Pls slow down.
            68Over Speed. Pls slow down.
            69Over Speed. Pls slow down.
            70Over Speed. Pls slow down.

-70まで印刷した後、オブジェクトbがプログラムで使用されていない場合でも、「クラスBike ...で呼び出されたfinalizeメソッド」が印刷されないため、JVMによってbがクリアされるかどうかは不確かです。


10
呼び出しSystem.gc();は、ガベージコレクションが実際に実行されることを保証するものではありません。
Simon Forsberg、2015

3
また、実行されるコレクションの種類も保証されません。ほとんどのJava GCは「世代別」コレクターであるため、関連しています。
スティーブンC

5

finalizeはクラス作成のカウントを出力します。

protected void finalize() throws Throwable {
    System.out.println("Run F" );
    if ( checkedOut)
        System.out.println("Error: Checked out");
        System.out.println("Class Create Count: " + classCreate);
}

メイン

while ( true) {
    Book novel=new Book(true);
    //System.out.println(novel.checkedOut);
    //Runtime.getRuntime().runFinalization();
    novel.checkIn();
    new Book(true);
    //System.runFinalization();
    System.gc();

ご覧のように。次の出力は、クラスカウントが36のときに初めて実行されたgcを示しています。

C:\javaCode\firstClass>java TerminationCondition
Run F
Error: Checked out
Class Create Count: 36
Run F
Error: Checked out
Class Create Count: 48
Run F

4

最近(テスト中に接続プールを破棄するために)ファイナライザメソッドに取り組んできたので、ファイナライザには多くのものが欠けていると言わざるを得ません。VisualVMを使用して観測するだけでなく、弱参照を使用して実際の相互作用を追跡すると、Java 8環境(Oracle JDK、Ubuntu 15)で次のことが当てはまることがわかりました。

  • ファイナライズはすぐには呼び出されません
  • デフォルトのガベージコレクターは到達できないオブジェクトをプールします
  • Finalizeは、ガベージコレクターがリソースを解放する特定のフェーズがあるという実装の詳細を指すように一括で呼び出されます。
  • System.gc()を呼び出すと、オブジェクトが頻繁にファイナライズされることはなく、ファイナライザが到達不能オブジェクトをより迅速に認識できるようになります
  • スレッドダンプを作成すると、ほとんどの場合、ヒープダンプまたはその他の内部メカニズムの実行中にヒープオーバーヘッドが高くなるため、ファイナライザがトリガーされます。
  • ファイナライズの継ぎ目は、メモリ要件(より多くのメモリを解放する)、または特定の内部制限のファイナライズ拡大のためにマークされているオブジェクトのリストによってバインドされます。したがって、ファイナライズされるオブジェクトが多数ある場合、ファイナライズフェーズは、少数のオブジェクトと比較すると、より頻繁かつ早期にトリガーされます。
  • System.gc()がファイナライズを直接トリガーする状況がありましたが、それは参照がローカルで短命であった場合のみです。これは世代に関連している可能性があります。

最終的な考え

finalizeメソッドは信頼できませんが、使用できるのは1つだけです。ガベージコレクションの前にオブジェクトが確実にクローズまたは破棄されるようにすることで、寿命末期のアクションを伴うより複雑なライフサイクルを持つオブジェクトが正しく処理される場合に、フェイルセーフを実装できるようになります。それが私がそれをオーバーライドするために価値があると考えることができる1つの理由です。


2

オブジェクトは、ライブスレッドまたは静的な参照から到達できない場合、ガベージコレクションまたはGCの対象になります。つまり、オブジェクトの参照がすべてnullの場合、オブジェクトはガベージコレクションの対象になります。循環依存関係は参照としてカウントされないため、オブジェクトAにオブジェクトBの参照があり、オブジェクトBにオブジェクトAの参照があり、他のライブ参照がない場合、オブジェクトAとBの両方がガベージコレクションの対象になります。一般に、オブジェクトは次の場合にJavaのガベージコレクションの対象になります。

  1. そのオブジェクトのすべての参照は明示的にnullに設定されます。たとえば、object = null
  2. オブジェクトはブロック内に作成され、コントロールがそのブロックを終了すると、参照はスコープ外に出ます。
  3. オブジェクトが別のオブジェクトの参照を保持している場合に親オブジェクトをnullに設定し、コンテナーオブジェクトの参照をnullに設定すると、子オブジェクトまたは含まれているオブジェクトがガベージコレクションの対象になります。
  4. オブジェクトにWeakHashMapを介したライブ参照のみがある場合、ガベージコレクションの対象になります。

場合はfinal、オブジェクトのフィールドが遅い計算中に繰り返し使用され、オブジェクトはその後に使用することはありません、オブジェクトが最後まで生かされることになるソースコードは、フィールドを要求し、またはJITがにフィールドをコピーすることができ一時変数を使用して、計算前にオブジェクトを破棄しますか?
スーパーキャット2017

@supercat:オプティマイザは、最初にオブジェクトが作成されていない形式にコードを書き換えます。その場合、同期がオブジェクトの使用とファイナライザ間の順序付けを強制しない限り、コンストラクタが終了した直後にファイナライズされる可能性があります。
ホルガー2017年

@ホルガー:JITがオブジェクトの作成から破棄までの間に発生するすべてのことをJITが確認できる場合、JITがファイナライザを早期に起動する理由は何もありません。本当の問題は、ファイナライザが特定のメソッド内で起動できないようにするために、コードが何をする必要があるかです。.NETにはGC.KeepAlive()、GCにオブジェクトを使用する可能性があると想定させる以外に何もしない関数がありますが、Javaにはそのような関数はありません。volatileその目的のために変数を使用することもできますが、そのような目的のためだけに変数を使用することは無駄に思えます。
スーパーキャット2017年

@supercat:JITはファイナライズを起動せず、参照を保持しないようにコードを調整するだけですが、を直接エンキューすることは有益である可能性があるためFinalizerReference、GCサイクルがなく、参照。同期は、発生前の関係を保証するのに十分です。ファイナライズは(実際には)別のスレッドで実行される可能性があるため、とにかく正式に必要になることがよくあります。Java 9が追加される予定Reference.reachabilityFenceです
Holger

@Holger:JITがオブジェクトの作成を最適化するFinalize場合、JITがそれを直接行うコードを生成した場合にのみ、まったく呼び出されます。同期コードは通常、単一のスレッドでのみ使用されることを期待するオブジェクトに対して期待されますか?オブジェクトが破棄される前に元に戻す必要のあるアクションを実行する場合(たとえば、ソケット接続を開き、もう一方の端のリソースへの排他的使用を取得するなど)、コードがまだソケットを使用しているときにファイナライザが接続を閉じると、問題が発生します。 。コードが同期を使用するのは正常ですか?
supercat

2

finalizeメソッドは保証されていません。このメソッドは、オブジェクトがGCに適格になったときに呼び出されます。オブジェクトがガベージコレクションされない状況が多数あります。


3
不正解です。あなたが言っているのは、オブジェクトが到達不能になったときにファイナライズされるということです。実際にメソッドが収集されたときに呼び出されます。
スティーブンC

2

破壊された場合、オブジェクトはアクションを実行する必要があります。たとえば、オブジェクトにファイルハンドルやフォントなどの非Javaリソースがある場合、オブジェクトを破棄する前にこれらのリソースが解放されていることを確認できます。このような状況を管理するために、javaは「ファイナライズ」と呼ばれるメカニズムを提供しています。ファイナライズすることで、オブジェクトがガベージコレクターから削除されようとしているときに発生する特定のアクションを定義できます。ファイナライザをクラスに追加するには、finalize()メソッドを定義するだけです。Java実行時は、そのクラスのオブジェクトを削除しようとするたびに、このメソッドを呼び出します。finalize method()内オブジェクトを破棄する前に実行するアクションを指定します。ガベージコレクターは、実行状態を参照しなくなったオブジェクト、または間接的に参照している他のオブジェクトを定期的に検索します。アセットが解放される前に、Javaランタイムはオブジェクトのfinalize()メソッドを呼び出します。ファイナライズ()メソッドは、以下の一般的な形式を有します。

protected void finalize(){
    // This is where the finalization code is entered
}

保護されたキーワードへのアクセスファイナライズ()クラス外部コードによってが防止されます。finalize()はガベージコレクションの直前に呼び出されることを理解することが重要です。たとえば、オブジェクトがスコープを離れるときは呼び出されません。つまり、finalize()がいつ実行されるか、またはいつ実行されるかを知ることができません。その結果、プログラムは、システムリソースまたはオブジェクトによって使用されている他のリソースを解放する他の手段を提供する必要があります。プログラムの通常の実行ではfinalize()に依存しないでください。


1

finalizeメソッドをオーバーライドするクラス

public class TestClass {    
    public TestClass() {
        System.out.println("constructor");
    }

    public void display() {
        System.out.println("display");
    }
    @Override
    public void finalize() {
        System.out.println("destructor");
    }
}

finalizeメソッドが呼び出される可能性

public class TestGarbageCollection {
    public static void main(String[] args) {
        while (true) {
            TestClass s = new TestClass();
            s.display();
            System.gc();
        }
    }
}

メモリがダンプオブジェクトで過負荷になると、GCはfinalizeメソッドを呼び出します

実行して、頻繁に呼び出されるfinalizeメソッドが見つからないコンソールを確認します。メモリが過負荷になると、finalizeメソッドが呼び出されます。


0

Javaでは、呼び出される可能性のあるfinalize()というメソッドをオブジェクトで実装できます。

finalize()メソッドは、ガベージコレクターがオブジェクトを収集しようとすると呼び出されます。

ガベージコレクターが実行されない場合、メソッドは呼び出されません。

ガベージコレクターがオブジェクトの収集に失敗し、 再度実行しようとした場合、メソッドは2回目に呼び出されません。

実際には、実際のプロジェクトで使用することはほとんどありません。

呼び出されない可能性があり、2度呼び出されることは絶対にないことに注意してください。finalize()メソッドは、0回または1回実行できます。

次のコードでは、ガベージコレクターを実行する必要がある前にプログラムが終了するため、finalize()メソッドを実行しても出力は生成されません。

ソース


0

finalize()ガベージコレクションの直前に呼び出されます。オブジェクトがスコープ外になった場合は呼び出されません。これは、いつfinalize()実行されるか、または実行されるかどうかさえわからないことを意味します。

例:

ガベージコレクタが発生する前にプログラムが終了すると、finalize()は実行されません。したがって、他のリソースを適切に処理するためのバックアップ手順として、またはプログラムが通常の操作で使用する手段としてではなく、特別な用途のアプリケーションとして使用する必要があります。


0

https://wiki.sei.cmu.edu/confluence/display/java/MET12-J.+Do+not+use+finalizersで指摘されているように、

実行時間はJava仮想マシン(JVM)に依存するため、ファイナライザを実行する必要がある固定時間はありません。唯一の保証は、実行されるファイナライザメソッドが、関連付けられたオブジェクトに到達できなくなった後(ガベージコレクションの最初のサイクル中に検出されたとき)と、ガベージコレクタが関連付けられたオブジェクトのストレージを再利用する前に(ガベージコレクタの2番目のサイクル中に)そうすることです。 。オブジェクトのファイナライザの実行は、オブジェクトが到達不能になった後、任意の時間遅延する場合があります。その結果、オブジェクトのfinalize()メソッドでファイルハンドルを閉じるなど、時間を重視する機能を呼び出すと問題が発生します。


-3

理解を深めるためにこのプログラムを実行してみてください

public class FinalizeTest 
{       
    static {
        System.out.println(Runtime.getRuntime().freeMemory());
    }

    public void run() {
        System.out.println("run");
        System.out.println(Runtime.getRuntime().freeMemory());
    }

     protected void finalize() throws Throwable { 
         System.out.println("finalize");
         while(true)
             break;          
     }

     public static void main(String[] args) {
            for (int i = 0 ; i < 500000 ; i++ ) {
                    new FinalizeTest().run();
            }
     }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.