2012-01-13 1 views
3

私は、デストラクタを明示的に呼び出さなければならないネイティブCライブラリを参照するAPIをJavaで書いています。デストラクタが呼び出されない場合、私はネイティブメモリを使い果たします。ガベージコレクタをカスタマイズしてネイティブメモリリークを防止するには?

デストラクタを明示的に呼び出さないようにする方法はありますか?ガベージコレクタにデストラクタを呼び出す方法(おそらく私が使用しているネイティブメモリのサイズの見積もりに基づいています)

私はJavaがガベージコレクタをJava APIの一部として持っていないことを知っていますが、これを実現する方法がいくつかありますか?

+3

これは、Javaオブジェクトに '.finalize()'を定義するのが実際に便利な使い方の1つです。その中のネイティブオブジェクトを破棄します。また、ユーザがそれ自身を行うことができるようにメソッドを提供します(メソッドが呼び出されなかった場合は 'finalize()'を呼び出して教えます) – fge

答えて

3

オブジェクトの作成を制御できる場合は、ReferenceQueueをとるコンストラクタを使用してWeakReferenceを使用してオブジェクトを参照することができます。スコープから外れると、Referenceがキューに入れられ、独自のスレッドでキューをポーリングしてクリーンアップ機能を呼び出すことができます。

なぜですか? これは、ファイナライザをクラスに追加するよりも少し効率的です(gcに特別な処理を強制するため)。

編集は、次の2つ(同じ品のバリエーションが)それを説明します http://java.sun.com/developer/technicalArticles/javase/finalization/ http://www.devx.com/Java/Article/30192

ピーターLawreyは、彼が言うときに、非常に良い点があります。

そうであっても、待っていますGCをクリーンアップするのは非効率的な場合があり、必要な場合はリソースを明示的にクリーンアップする手段を公開することができます。

あなたは、あなたのユーザーがJava7であることを前提とし、新たなトライで-リソースを使用しているとき、それは彼らが自動的にそれを行うのに役立ちますようjava.lang.AutoCloseableを見てみることができますたび

1

ガベージコレクタは、JavaオブジェクトがGCdに近づいているときにfinalize()のJavaオブジェクトをコールし、finalizeの中でデストラクタを呼び出すことができます。 新しいを呼び出す必要があるすべてのデストラクタのJavaオブジェクトを作成し、デストラクタを呼び出すまでそのJavaオブジェクトへの参照を保持します。

finalize()は、技術的にJavaが特定のオブジェクトががGCdになるという保証がないにもかかわらず、遅かれ早かれ呼び出されます。唯一の例外は、プロセスがシャットダウンしているときにオブジェクトがまだ周辺にある場合です.GCdが実際には得られないことがあります。

2

finalize()の使用に加えて、呼び出しを行うためにリソースが不足した場合にGCを起動する必要があるかもしれませんが、GCは実行されていません。

ByteBuffer.allocateDirect()にこの問題があります。 GCがByteBuffersをクリーンアップする必要がありますが、GCがトリガーされる前に最大ダイレクトメモリにアクセスできるため、コードはこれを検出して、System.gc()を明示的にトリガーします。

GCがクリーンアップするのを待つことは効率が悪く、必要な場合は明示的にリソースをクリーンアップする手段を公開することができます。

関連する問題