web-dev-qa-db-ja.com

メモリリークは何ですか? Java.lang.ref.Finalizerが多くのメモリを消費する理由

プログラムでヒープダンプを実行しました。メモリアナライザツールで開いたとき、Java.lang.ref.Finalizer ために org.logicalcobwebs.proxool.ProxyStatementは多くのメモリを消費していました。これはなぜですか?

screenshot

59
fuyou001

一部のクラスはObject.finalize()メソッドを実装します。このメソッドをオーバーライドするオブジェクトは、バックグラウンドスレッドコールファイナライザによって呼び出される必要があり、これが発生するまでオブジェクトをクリーンアップすることはできません。これらのタスクが短く、これらの多くを破棄しない場合、すべて正常に機能します。ただし、これらのオブジェクトを多数作成している場合や、ファイナライザに長時間かかる場合は、ファイナライズするオブジェクトのキューが蓄積されます。このキューがすべてのメモリを使い果たす可能性があります。

解決策は

  • 可能であればfinalize()dオブジェクトを使用しないでください(オブジェクトのクラスを作成している場合)
  • ファイナライズを非常に短くする(使用する必要がある場合)
  • そのようなオブジェクトを毎回破棄しないでください(再利用してみてください)

既存のライブラリを使用しているため、最後のオプションが最適です。

63
Peter Lawrey

私が理解できることから、ProxoolはJDBC接続の接続プールです。これは、問題はアプリケーションが接続プールを誤用していることであることを示唆しています。ステートメントオブジェクトでcloseを呼び出す代わりに、コードはおそらくそれらおよび/またはその親接続をドロップしています。 Proxoolは、基になるドライバー実装オブジェクトを閉じるためにファイナライザーに依存していますが、これにはそれらのファイナライザーインスタンスが必要です。また、接続が(実際の)データベース接続を必要以上に頻繁に開いたり閉じたりしていることを意味している可能性があり、これはパフォーマンスに悪影響を及ぼします。

したがって、漏れたResultSet、Statement、Connectionオブジェクトのコードをチェックし、finallyブロックでそれらを閉じることを確認することをお勧めします。


メモリダンプを見ると、898,527,228バイトがどこに向かっているのか気になると思います。大部分は、IDが2aab07855e38であるFinalizerオブジェクトによって保持されます。ダンプファイルがまだある場合は、thatFinalizerが参照しているものを見てください。 Proxoolオブジェクトよりも問題が多いようです。

9
Stephen C