SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

Javaファイナライズのメモリ保持問題への対処方法

JVMのファイナライズ処理の仕組みとテクニック

  • このエントリーをはてなブックマークに追加

Javaのファイナライズ機能はオブジェクトの事後クリーンアップを可能にしますが、ファイナライズを明示的に使っていない場合でも、リソースの再生に遅延が生じることがあります。本稿では、このようなメモリ保持問題を回避する方法について説明します。

  • このエントリーをはてなブックマークに追加

はじめに

 Javaのファイナライズ機能は、ガベージコレクタが到達不能と判断したオブジェクトに対して事後クリーンアップを実行するための仕組みです。通常は、オブジェクトに関連付けられたネイティブリソースを再生(reclaim)する場合に使います。簡単なファイナライズの例を次に示します。

public class Image1 {
    // pointer to the native image data
    private int nativeImg;
    private Point pos;
    private Dimension dim;

    // it disposes of the native image;
    // successive calls to it will be ignored
    private native void disposeNative();
    public void dispose() { disposeNative(); }
    protected void finalize() { dispose(); }

    static private Image1 randomImg;
}

 Image1のインスタンスが到達不能になると、Java仮想マシン(JVM)は状況に応じて、画像データ(この例では整数型のnativeImgで参照)を保持しているネイティブリソースを確実に再生するためにImage1finalize()メソッドを呼び出します。ここで注意してほしいのは、finalize()メソッドはJVMによって特殊な扱いを受けるものの、任意のコードからなる任意のメソッドだという点です。具体的には、finalize()メソッドはオブジェクト内のすべてのフィールド(この例ではposdim)にアクセスできます。また、驚くべきことに、finalize()メソッドの中でオブジェクトを再び到達可能にすることもできます(たとえばrandomImg = this;として静的フィールドから到達可能にするなど)。このプログラミング手法はあまりお勧めしませんが、方法としては可能です。

 ここで、ファイナライズ可能なオブジェクト(クラスに有効なファイナライザが定義されているオブジェクト)が作成されてから回収されるまでの流れを見てみましょう。オブジェクトの名前はobjとします(図1を参照)。

図1 ファイナライズ可能なオブジェクトobj
図1 ファイナライズ可能なオブジェクトobj
  1. objが割り当てられるときに、JVMはobjがファイナライズ可能であることを内部に記録します(通常はこれによってJVMの高速割り当てパスの速度が低下します)。
  2. ガベージコレクタがobjを到達不能と判断します。このとき、ガベージコレクタは割り当て時の記録からobjがファイナライズ可能であることを認識し、このオブジェクトをJVMのファイナライズキューに追加します。また、その時点で到達不能になっているオブジェクトでも、それがobjから到達可能なオブジェクトであれば、ファイナライザからアクセスされる可能性があるのですべて保持します。図2に、Image1インスタンスの場合の例を示します。
  3. その後、JVMのファイナライザスレッドobjをキューから取り出し、objfinalize()メソッドを呼び出して、ファイナライザが呼び出されたことを記録します。この時点で、objは「ファイナライズ済み」と見なされます。
  4. ガベージコレクタが再びobjを到達不能と判断しますが、今度はファイナライズ済みなので、objのスペースと、objオブジェクトから到達可能なすべてのオブジェクト(ただし他から到達不能なもの)を回収します。
図2 ガベージコレクタがobjを到達不能と判断する
図2 ガベージコレクタがobjを到達不能と判断する

 ガベージコレクタがobjを回収するのに最低でも2サイクルを必要とし、このプロセス中はobjから到達可能なすべてのオブジェクトを保持する必要があることに注意してください。この点を忘れていると、一時的に予想外のリソース保持問題が発生する可能性があります。もう1つ注意してほしいのは、JVMは、割り当てられたすべてのファイナライズ可能なオブジェクトのファイナライザを呼び出すとは限らないという点です。ガベージコレクタが一部のオブジェクトを到達不能と見なす前にJVMが終了することもあります。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
サブクラス作成時のメモリ保持問題を回避する

修正履歴

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Tony Printezis(Tony Printezis)

SunLabsでの3年以上の勤務を経て、Sun MicrosystemsのJava HotSpot Virtual Machine開発チームに参加。主に、ガベージコレクタのスケーラビリティ、反応性、並列性、ビジュアル化を中心に、動的メモリ管理に携わる。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/337 2006/04/11 19:12

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング