2011-12-02 5 views
51

私のプログラムでヒープダンプを実行しました。私がメモリアナライザツールでそれを開いたとき、のjava.lang.ref.Finalizerが大量のメモリを占めていることがわかりました。なぜこれはそうですか?はメモリリークですか?なぜjava.lang.ref.Finalizerはあまりにも多くのメモリを食べますか

screenshot

+0

「画像」リンクは、あなたのツイッタープロファイルのように見えます。 –

+0

@ R.MartinhoFernandesそれは彼がTwitterでホストしてきたイメージに行くと思う。 – Oliver

答えて

49

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

ソリューションです

  • あなたは(あなたがオブジェクトのクラスを記述している場合)ことができれば、あなたがそれを使用する必要がある場合
  • は(非常に短い確定作るファイナライズ()Dオブジェクトを使用していません)
  • は、そのようなオブジェクトを毎回破棄しない(

最後のオプションでは、既存のライブラリを使用しているとして、あなたのための最良である可能性が高い)、それらを再利用してみてください。

+12

オプション#4 - ファイナライザを(オーバー)使用するライブラリの使用を避けてください。 –

+3

オプション#1;のバリエーション) –

+0

おそらく問題はFinalizerスレッドの原因です。 1つのクラスがfinalizeのメソッドをオーバーライドし、Finalizerスレッドのデッドロックを引き起こします – fuyou001

7

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

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


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

+0

ありがとう、しかし、私はJDBC接続のポーリングmemoyリークの原因を見つけることができません – fuyou001

+0

私はあなたのソースコードが表示されない限り、どちらもできません。 (そして私はとにかくそれを通り抜けて私の時間を過ごす準備ができていない...) –