web-dev-qa-db-ja.com

Javaのfinalize()の置き換え

Object.finalize()はJava 9で廃止予定です。その理由は理解できたと思いますが、置き換える方法がわかりません。

私はConfigurationと呼ばれるユーティリティクラスを持っています。このクラスには基本的に、アプリケーションのすべてを所有し、アプリケーションの期間中持続する単一のインスタンスがあります。それが提供するサービスの1つはロギングです。メッセージをログに記録する最初の要求で、構成オブジェクトのフィールドに参照が保持されているロガーが作成されます(さまざまなレガシーな理由により、標準のロガーではなく自分のロガーです)。アプリケーションの終了時に、正常か異常かにかかわらず、ロガーが保持しているすべてのリソースを解放したい(私のライブラリのユーザーが独自の実装を提供できるため、これはブラックボックスです)。

現在、これはConfiguration.finalize()を呼び出すlogger.close()メソッドで実現されています。

代わりに何をすべきですか?

13
Michael Kay

ファントム参照finalize()の一般的な置き換えです。 Javaランタイムの多くのクラスがすでにそれらを使用しています。

ファントム参照 の使用は少し面倒です。独自の参照リストと事後処理スレッドを維持する必要があります。一方、あなたは完全にコントロールしています。

これは簡単な例です ファントム参照設定の。

この記事 Java finalize()および ファントム参照 の実装について説明および比較します。

6
Alexey Ragozin

Java 9は Cleaner とCleanableユーティリティクラスを導入し、キューへのファントム参照とそのキューから排出されるクリーニングスレッドへの関連付けを処理します。

これにより、所有しているオブジェクトが停止した後に事後のクリーンアップを実行するウィットネスを分離できますが、GCによってトリガーされるリソース管理に関するすべての警告が引き続き適用されます。つまり、AutoClosableとガベージコレクターではなく、リソースのライフサイクルを管理するためのtry-with-resourcesブロック。

6
the8472

スレッドを shutdown hook としてランタイムに追加できます。

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    // cleanup code
}));

これは、VM=が終了したときに呼び出されるため、特定のケースではfinalizeの適切な置き換えとなるはずです。

3
Lothar

IMHOロガーに自分の混乱をクリーンアップするように指示するのは、アプリケーションの責任ではありません。ロガー自体はできますすべき(IOストリームまたはDB接続とは異なり)としてそれを行います、それは長く生きることになっています。

しかし、あなたはすでにlogger.close()...を提供しています... OK、それから私は以下を提案するでしょう:

  • closeがべき等であることを確認します。つまり、ロガーを2回閉じても何も起こりません。
  • _Runtime#addShutdownHook_とPhantomReferenceの両方を使用し、両方がlogger.close()を呼び出せるようにして、JVMが終了したとき、またはアプリケーションがGCされたときに両方が呼び出されるようにします。
2
maaartinus