jProfiler を使用して、Java Swing アプリケーションのメモリ リークを見つけています。数が増え続ける JFrame のインスタンスを特定しました。
このフレームは開いてから閉じます。
jProfiler を使用して GC ルートへのパスを表示すると、「JNI グローバル参照」という 1 つの参照しかありません。
これは何を意味するのでしょうか?フレームの各インスタンスにぶら下がっているのはなぜですか?
JNIグローバル参照は、「ネイティブ」コードからJavaガベージコレクターによって管理されるJavaオブジェクトへの参照です。その目的は、ネイティブコードでまだ使用されているが、Javaコードにライブ参照がないように見えるオブジェクトの収集を防ぐことです。
JFrameはでありjava.awt.Window
、「ネイティブ」ウィンドウオブジェクトに関連付けられています。特定のJFrameインスタンスを完全に終了したら、そのdispose()
メソッドを呼び出してクリーンアップする必要があります。
ネイティブコードがJFrameへのグローバル参照を作成しているかどうかはわかりませんが、可能性が高いようです。その場合、これによりJFrameがガベージコレクションされなくなります。多くのWindows(またはサブクラス)を作成していて、それらが収集されないことがわかっている場合は、それらが破棄されていることを確認してください。
ウィキペディアにはJava Native Interfaceの概要があり、基本的に Java と他の言語で記述されたネイティブ オペレーティング システム ライブラリとの間の通信を可能にします。
JNI グローバル参照は、自動的にガベージ コレクションが行われないため、メモリ リークが発生しやすく、プログラマが明示的に解放する必要があります。JNI コードを自分で作成していない場合は、使用しているライブラリにメモリ リークがある可能性があります。
edit hereは、ローカル参照とグローバル参照、およびグローバル参照が使用される理由 (およびそれらを解放する方法) についてのもう少しの情報です。
JavaFX アプリケーションでメモリ リークを修正するときに、まさにこの問題が発生しました。結局、問題は、アプリケーションをデバッグ モードで実行していて、コードにいくつかのブレークポイントがあることが判明しました。これにより、オブジェクトが「JNI グローバル参照」になり、明らかな理由もなくメモリに保持されているようです。デバッグモードをオフにすると、すべてが正常に機能しました!