ホームページ  >  記事  >  Java  >  Javaでfinalizeの使用を禁止する方法の紹介

Javaでfinalizeの使用を禁止する方法の紹介

黄舟
黄舟オリジナル
2017-10-14 09:37:551223ブラウズ

この記事では主にJavaでのfinalizeメソッドの使用禁止について紹介します

finalizeメソッドとは

finalize()メソッドはJava.lang.Objectで定義されています。つまり、すべてのクラスがこのメソッドをオーバーロードできるということです。 Java ガベージ コレクターは、new によって割り当てられたメモリのみを解放できるため、オブジェクトが new によって取得されたメモリでない場合、ガベージ コレクターはオブジェクトのメモリを解放する方法を知りません。

この状況に対処するために、Java では java.lang.Object クラスの Finalize() メソッドをクラス内でオーバーライドできるようにしています。

仕組み: ガベージ コレクターがオブジェクトによって占有されているストレージ領域を解放する準備ができると、その Finalize() メソッドが最初に呼び出され、オブジェクトによって占有されていたメモリは次のガベージ コレクション アクションまで実際には再利用されません。が発生します。

ファイナライズ関数の呼び出しメカニズム

Java仮想マシンの仕様では、ガベージコレクションを実行するかどうか、およびどのように実行するかを厳密に規定していません。したがって、ここで説明した呼び出しメカニズムがすべての JVM に適しているとは保証されません。

いつ呼ばれますか?

ファイナライズはいつ呼び出されますか?一般に、JVM がガベージ コレクションを開始するまでは呼び出されません。 JVM がガベージ コレクションを実行する時点は非常に不確実で、さまざまな実行時環境要因に依存します。ファイナライズ関数の呼び出し時間は不確実であるため、後述するいくつかの欠点が生じます。

誰が電話しますか?

一般的な JVM は、GC のガベージ コレクション スレッドを通じてファイナライズ関数を呼び出します。ガベージ コレクション スレッドは非常に重要であるため (結局のところ、ガベージ コレクション スレッドは JVM の不可欠な部分でもあります)、ファイナライズ関数によってスローされた例外がガベージ コレクション スレッドの動作に影響を与えるのを防ぐために、ガベージ コレクション スレッドは次の処理を実行します。各ファイナライズ関数を呼び出すときに catch を試みます。 If 例外がキャッチされると、例外は直接破棄され、次の無効なオブジェクトのファイナライズ関数が処理されます。

finalize()の使用が禁止されている理由

1. 呼び出し時間が不確実です---リソースの無駄遣いのリスクがあります

この呼び出しメカニズムは以前に導入されました。学生は「finalize を呼び出すタイミングは非常に不確実である」という事実を認識する必要があります。したがって、finalize() で不足しているリソースを解放すると、その不足したリソースが解放されるまでに長い時間がかかる可能性があります。これは資源の無駄遣いです。さらに、特定のクラス オブジェクト (一部の JDBC クラスなど) によって運ばれるリソースは、それ自体で大量のメモリを消費する可能性があり、これらのリソースの解放が遅れると、パフォーマンスに大きな問題が発生します。

2. 呼び出されない可能性があります---リソース漏洩のリスクがあります

多くの学生は、finalize() が常に呼び出されると考えていますが、そうではありません。場合によっては、finalize() がまったく呼び出されないこともあります。たとえば、JVM が終了すると、メモリ内のそれらのオブジェクトのファイナライズ関数が呼び出されない可能性があります。

一部の学生は、JVM が終了する前にすべてのファイナライズが確実に呼び出されるようにするために「runFinalizersOnExit」を考えていると推定されます。 JDK 1.2 以降、このメソッドが廃止されたのは残念であり、残念です。たとえこの方法が放棄されなかったとしても、スレッドの安全性を脅かす大きな危険が依然として存在します。

上記からわかるように、リソースの解放を支援するために Finalize() に依存すると、それは非常に悪いことになります (リソース漏洩のリスクがあります)。多くの場合、リソース リークによって引き起こされるパフォーマンスの問題はより深刻であり、過小評価すべきではありません。

3. ファイナライズ関数が呼び出されたときにオブジェクトが復活する可能性があります

本来は、オブジェクトの有効期限が切れた(参照がない)場合にのみ、ガベージコレクタはオブジェクトのファイナライズ関数を呼び出します。ただし、ひねくれたプログラマに遭遇し、オブジェクト自身の参照 (つまり this) を Finalize() 関数内のどこかに再保存した場合、それは自分自身を復活させることと同じです (オブジェクトは新しい参照を持ち、無効な状態ではなくなっているため)州)。 この奇妙なことが起こらないようにするために、ガベージ コレクターは、finalize() を呼び出すたびにオブジェクトがまだ無効な状態にあるかどうかを確認することしかできません。これにより、実質的に JVM のオーバーヘッドが増加します。さりげなく言及してください。 JDK のドキュメントで規定されているように、JVM はクラス オブジェクト インスタンスごとに多くても 1 回だけ Finalize() を呼び出します。したがって、偽の死体のインスタンスの場合、実際に死亡したときに Finalize() は呼び出されません。これは奇妙だと思いませんか?

4. 例外を自分でキャッチすることを忘れないでください

Finalize() 呼び出しメカニズムを導入するときに述べたように、例外が Finalize 関数の外でスローされると、その例外はガベージ コレクション スレッドによってキャッチされて破棄されます。言い換えれば、例外は無視されます (無視された例外の危険性については「ここ」で説明されています)。このようなことを防ぐには、finalize() で例外をスローする可能性のあるコードに対して try catch ステートメントを作成し、それを自分でキャッチする必要があります。

5. スレッドの安全性に注意してください

finalize() はガベージ コレクション スレッドによって呼び出されるため、独自のコードと同じスレッドではありません。異なるオブジェクトの Finalize() であっても、異なるガベージ コレクション スレッドによって呼び出される可能性があります (「並列コレクター」を使用する場合など)。 。したがって、finalize() で特定のデータにアクセスするときは、スレッドの安全性の問題に常に注意を払う必要があります。

概要

以上がJavaでfinalizeの使用を禁止する方法の紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。