「Javaパフォーマンスチューニング 第5回 メモリ・リークの発見」

http://www.atmarkit.co.jp/fjava/rensai3/devedge05/devedge05_1.html
毎度のことだが,これをメモリリークと呼ぶのは間違いだと思う.

メモリリーク:既にそのインスタンスへの参照がなくなり,到達可能(reachable)で無くなったオブジェクトの領域が永久に解放されなくなる現象.

これに対しJavaで起こるのは,

そのインスタンスへの参照が残っており,到達可能であるオブジェクトの領域が永久に開放されなくなる現象.

である.これは肥大化と呼ばれる現象の一種で*1,通常はメモリリークとは呼ばない.
メモリリークは「死んだオブジェクト」がメモリを消費し続ける現象であるのに対し,『肥大化』は「生きているオブジェクト」がメモリを消費し続ける現象だ.生きているオブジェクトが解放されないのはごくごく当たり前のことだ.

これも何度か言っていることだが

GCは『プログラマーが今後二度と使わないつもりのオブジェクト』を解放するものではない.『二度と使われないことが保証されているオブジェクト』を解放する物だ.

二度と使われないことが保証されているということは即ち到達不可能であるということであり,それを「死んだオブジェクト」と呼ぶ.プログラマーが二度と使わないつもりでも到達可能なオブジェクトは,GC的には全て「生きているオブジェクト」と見なされる*2メモリリークとは「死んだオブジェクト」がメモリを占有し続ける現象のことを指し,これはJavaのようにGCのある言語では発生しない.

ちなみにいわゆる「null参照クリア」は,一部のオブジェクトで必要になることもあるが,あまり好ましいコーディングスタイルではない*3.(少なくともJavaでは)null参照クリアよりは参照変数のスコープを小さくすることが推奨されている.

*1:それほど特殊な現象ではないため,これだけを区別する名称はおそらくない.これと同じことはどんな言語でもどんな環境でも起こりうる.

*2:このあたりはGCの基本的な性質になる.到達不可能なオブジェクトはいずれ必要に応じて回収されるが,その全てが即時回収されるとは限らない.また到達可能なオブジェクトについては,それが回収されることは絶対にない.もし到達可能なオブジェクトまで回収されるれば,アプリの正常な動作は保証されなくなる.これは即ちGCのバグである.

*3:null参照クリアは必ずしも必要ががない上に,記述漏れが発生しやすい.パフォーマンス的にも若干不利になる事が多い.少なくとも早くはならない.