メモ(Java でのガーベッジコレクション)

Java では使い終わったインスタンスは、基本的にはホッタラカシで良い。インスタンスを参照する変数がスコープから外れれば、インスタンスへの参照がなくなり、それをガーベッジコレクタが検出してガーベッジコレクションの対象としてくれる。
ただし、インスタンスが native なリソースを参照している場合は、通常はそのリソースを解放するためのメソッドが備わっているので、インスタンスを使わなくなると分かった時点で速やかにそれらの解放用メソッドを呼ぶ必要がある。native なリソースが絡まなければ単純なメモリ管理だけなので、ガーベッジコレクタに任せてしまえばよいが、native なリソースが絡むと、そのようなリソースまでの解放はガーベッジコレクタが直接管理できず、Javaインスタンスガーベッジコレクションされた後に、おもむろに finalize が呼ばれ、その段階でやっと副次的に native のリソースが解放されるためである。
native なリソースが絡むクラスにはつぎのものがあり、以下にクラスと解放用メソッドを示す。

  • InputStream/OutputStream クラス(良く使うサブクラスは FileInputStream/FileOutputStream): close メソッド
  • Image クラス: flush メソッド
  • Window クラス(良く使うサブクラスは Frame/JFrame): dispose メソッド
  • Graphics クラス: dispose メソッド

ただし Component クラスの paint/paintComponent メソッドの引数としての Graphics はそのメソッドの呼び出し側でリソース管理するので、paint/paintComponent メソッド内で dispose してはいけない。自分で getGraphics した場合のみ dispose する。
サブクラスによっては native のリソースが絡まない場合もあるが、常に作法として close/flush/dispose は呼ぶようにすべき。たとえば BufferedImage がこれに該当するが、Component クラスの createImage で得られる Image の実行時の具象クラスがなにであるかは実行環境次第なので、どのような具象クラスであっても dispose すべき。