凪瀬 Blog
Programming SHOT BAR

目次

Blog 利用状況
  • 投稿数 - 260
  • 記事 - 0
  • コメント - 2230
  • トラックバック - 192
ニュース
広告
  • Java開発者募集中
  • 経歴不問
  • 腕に自信のある方
  • 富山市内
  • (株)凪瀬アーキテクツ
アクセサリ
  • あわせて読みたい
凪瀬悠輝(なぎせ ゆうき)
  • Java技術者
  • お茶好き。カクテル好き。
  • 所属は(株)凪瀬アーキテクツ
  • Twitter:@nagise

書庫

日記カテゴリ

 

本日のカクテルは「Javaのメモリ管理」です。

ネタ元はかつのりさんのBlogです。
GCについて勘違いしている人が結構多い

JavaというとGC(ガーベッジコレクション)によって不要となったオブジェクトが回収される仕組みになっていますので、一般のプログラマはメモリの確保、解放について考える必要がありません。
ただし、プロフェッショナルなプログラマの方は一般のプログラマの分まで背負い込んで考えてもらう必要があります。
C言語のようにメモリの割り当てと解放を直接管理することはありませんが、まったく別種のメモリ管理が必要となってきます。

参照の種類

「要するに、参照がなくなればGCに回収される、参照があれば回収されない、それだけのことだろう?」
こうおっしゃるお客さんは沢山いらっしゃいます。では、参照にも種類があることをご存じですか?

  • 強い参照 (strong reference)
  • ソフト参照 (soft reference)
  • 弱い参照 (weak reference)
  • ファントム参照 (phantom reference)

このあたりについてもかつのりさんが過去に紹介済みなのですが( java.lang.refパッケージの活用) こちらでは視点を変えてお話ししてみたいと思います。

  • 強い参照で到達できるオブジェクトはGCに回収されない
  • 強い参照がなく、ソフト参照到達できるオブジェクトはメモリが一杯であるなどの条件により回収されることがある
  • 強い参照やソフト参照がなく、弱い参照到達できるオブジェクトはGCに回収される
  • ファントム参照はもはやなくなったオブジェクトへの参照

このように、参照には種類があります。Javaによるメモリ管理とは、これらの参照の特徴を利用してオブジェクトの廃棄をうまく管理してやることになります。 これが、C言語とはまったく別種のメモリ管理というわけです。

参照の作り方

通常、オブジェクトをnewして変数に入れますが、これらはすべて強い参照となります。 そのほかの参照はどうやって作るのでしょうか?
java.lang.refパッケージにこれらの参照を使うためのクラスが用意されています。

  • java.lang.ref.SoftReference<T>
  • java.lang.ref.WeakReference<T>
  • java.lang.ref.PhantomReference<T>

の3つのクラスを利用します。 たとえばソフトな参照を作りたければ、


Object o = new Object();
Reference<Object> ref = new SoftReference<Object>(o);

というようにコンストラクタの引数に対象オブジェクトを渡します。 ソフト参照からオブジェクトを取得する場合は


Object o = ref.get();
if (o == null) {
  // GCで回収されている
}

とget()するだけなのですが、GCで回収されている可能性がありますので、常にnullチェックを必要とします。

また、強い参照がなくなってソフトな参照だけになった、などといった参照到達性の変更は
java.lang.ref.ReferenceQueue<T>
を各種Referenceのコンストラクタ引数に渡すことで検出できます。


Object o = new Object();
ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
Reference<Object> ref = new SoftReference<Object>(o, queue);

このようにしておくと、queue.poll()もしくは、queue.remove()とすることで、SoftReferenceのコンストラクタ引数で渡したObjectがソフトな参照だけになった場合にSoftReferenceオブジェクトを取得することができます。
つまり、参照到達性の変更にフックすることができるわけです。

参照の使い方

では、これらの参照はどうやって使うのでしょう?

ソフト参照は、キャッシュを実装する際によく用いられます。
DBを参照して取得してくるような、生成コストの高いオブジェクトはキャッシュしたいところです。
しかし、むやみにキャッシュするとOutOfMemoryエラーとなってしまう…。
そこで、ソフト参照の性質を利用します。
OutOfMemoryとなる前にソフト参照は回収されることが保障されていますから、メモリの確保できる限りはキャッシュしておく、ということができるのですね。

弱参照はjavadocでは正規化マッピングの実装に使われると書いてあるのですが、つまるところ草葉の陰から見守るような使い方をするときに利用します。
Factoryパターンなどで発給したオブジェクトを管理するためにFactory内に参照を持っておきたいというケースを想定しましょう。
しかし、もう使わなくなったよ!ということを検出することは通常ではできません。
I/O関係のclose()メソッドのように使い終わったら必ずこのメソッドを呼び出してね、というルールをjavadocで明示することはできても、コンパイルエラーになるわけではないですから使い手がうっかりすればリークしてしまいますね。
そういうときに弱参照を利用します。Factory内では発給したオブジェクトへの弱参照を保持しておきます。
強い参照がなくなると弱参照だけになり、GCに回収されますから、リークすることはありません。
強い参照が残っている間だけ、該当のオブジェクトにアクセスすることができるのです。

ファントム参照ファイナライザの代わりに利用することができます。
java.lang.Object#finalize()
を利用するよりも柔軟にオブジェクト回収時の処理を行うことができます。
ファントム参照はGC対象だがまだ完全に削除されていないオブジェクトへの参照です。
ここで強い参照に戻せてしまうと困るのでget()メソッドは常にnullを返します。 ですから、ReferenceQueueを利用した使い方しかできません
ファントム参照が生きている間はオブジェクトはGCによってクリアされません。
ファントム参照をずっと保持しているとメモリリークを起こすことになりますので注意しましょう。

最後に

JavaはGCがメモリ管理するからメモリを意識することはない、せいぜい、無駄な参照があってGC回収対象にならないことがないように気をつければよいだけさ、なんて考えが吹き飛んでいただけたなら幸いです。
共通ライブラリを作る際にはこれらの参照を駆使して、使い手には意識させないメモリ管理をひっそりと行いましょう。

本日のカクテルは楽しんでいただけたでしょうか?

投稿日時 : 2007年7月29日 10:55
コメント
  • # re: Javaのメモリ管理
    επιστημη
    Posted @ 2007/07/29 11:59
    ますたー、のっけから'こゆい'よー
  • # re: Javaのメモリ管理
    melt
    Posted @ 2007/07/29 12:26
    何か Java がものすごく良い言語に見えてきましたw

    ref.get() で null チェックをした直後に GC で回収されたらどうなるんだろうと思ったんですが、ref.get() で代入した時点で強い参照になってるから大丈夫なんですね。

    ということは、
    if (ref.get() == null)
    {
      ...
    }
    っていう書き方はダメなんですか?
  • # re: Javaのメモリ管理
    かつのり
    Posted @ 2007/07/29 12:42
    キレイにまとまってますな~。
    しかしファントム参照の使い方だけはいつも悩む・・・
  • # re: Javaのメモリ管理
    nagise
    Posted @ 2007/07/29 13:22
    >επιστημηさま

    普通の話題はそこらのバーで聞いてくださいw

    >meltさま
    同期処理の可能性からいえば、ref.get()を繰り返しているさなかにGCで回収されることはあり得ます。
    変数への代入で強い参照を作ってから確認する手順にしないと再現性の低いNullPointerに悩まされるのではないでしょうか。

    >かつのりさま
    ファントム参照はファイナライザの代用と考えるのが良いようです。もっとも、Object#finalize()と同等に呼ばれるタイミングは不明なのですけども。
  • # re: Javaのメモリ管理
    かつのり
    Posted @ 2007/07/29 14:18
    ファントム参照が参照キューから取得できても、
    実際にインスタンスが参照できないんで、
    この辺がfinalizeの代わりに使いにくいところですね。

    実際に使うとなると、例えばjava.io.Fileとか。
    ファイルを作成>ファントム参照にファイルを示す文字列とファイルを格納
    って感じにしてキューから参照を取得したときに、再度ファイルのインスタンスを文字列から生成して削除するとか。

    たまにリフレクションでファントム参照からインスタンスを取得するサンプルを見ますが、
    あれは微妙だと思ったりもします。
  • # re: Javaのメモリ管理
    凪瀬
    Posted @ 2007/07/29 15:29
    ファントム参照から本来消されるはずの参照を復活させることはできないはず。
    PhantomReference.get()は常にnullを返しますし、そもそも参照到達性でいえば、到達できなくなってからファントム参照になるのですから。

    消されるはずの参照を直接持つのではなく、ファイナライザとして動くオブジェクトを別途用意しておき、PhantomReferenceをキーにファイナライザオブジェクトを取得できるMapを用意して管理するような感じになるのではないでしょうか。
    ファイナライザで処理したいリソースは強参照で強く到達可能でも、そのリソースを保有するオブジェクトは到達不可能になってファントム参照となるわけです。
  • # re: Javaのメモリ管理
    かつのり
    Posted @ 2007/07/29 18:51
    あれ?たしかPhantomReference#referentというプライベートのフィールドにはまだ参照が残っていますよ。
    でもGCの対象としてマーク済みなので、参照を復活させたら二度とGCの対象にはならないはず。。。

    この辺はやっちゃいけない領域なんですよね。
  • # re: Javaのメモリ管理
    凪瀬
    Posted @ 2007/07/29 19:29
    > PhantomReference#referentというプライベートのフィールドにはまだ参照が残っていますよ。

    そりゃぁいじっちゃ駄目でしょうw
    わざわざリフレクションでアクセスレベル無視してまで参照をひっぱりだすなんて狂気の沙汰ですw
  • # re: Javaのメモリ管理
    じゃんぬねっと
    Posted @ 2007/07/29 22:28
    いいですねぇー。早速やってくださっている。
    私も技術ネタくらいたまに提供しないといけないですね。
  • # re: Javaのメモリ管理
    むら
    Posted @ 2007/07/30 15:47
    Javaのお話ではありますが、使い道など相当ヒントを頂きました!
    なるほど... .NETではWeakReferenceクラスが関係するところですな...
  • # re: Javaのメモリ管理
    凪瀬
    Posted @ 2007/07/30 16:17
    私は.NETは軽くしかいじっていないので分からないのですが、ほぼ同等の機能を持っているのではないでしょうか。
    .NET版をまとめてもらえると嬉しいですね。

    「VM上で動作するGCを持つ言語」という括りでのメモリ管理という話に拡張できる気がしますね。
  • # re: Javaのメモリ管理
    じゃんぬねっと
    Posted @ 2007/07/31 15:27
    .NET の GC で知っているのはジェネレーションという仕組みくらいですね。このあたりは囚人さんの方が断然知っておられると思います。ということで、囚人さん頼むw
  • # re: Javaのメモリ管理
    凪瀬
    Posted @ 2007/07/31 17:02
    これらのクラスの導入がJDK1.2からなのを考えるとJ++ではサポートされていないのでしょうかね。
    そうするとその後のJ#とかでもJavaの本流側を追従して機能拡張しているわけではないですから.NETのGCには同等の機能が無くても矛盾は生じないか。
  • # .NETのメモリ管理
    むらぶろ - .NETって面白い -
    Posted @ 2007/08/01 13:24
    .NETのメモリ管理
  • # .NETのメモリ管理
    むらぶろ - .NETって面白い -
    Posted @ 2007/08/01 13:27
    .NETのメモリ管理
  • # 11月のアクセス
    凪瀬 Blog
    Posted @ 2007/12/01 13:21
    11月のアクセス
  • # Posts like this brghietn up my day. Thanks for taking the time.
    Jayce
    Posted @ 2012/01/28 3:54
    Posts like this brghietn up my day. Thanks for taking the time.
  • # Posts like this brghietn up my day. Thanks for taking the time.
    Jayce
    Posted @ 2012/01/28 3:54
    Posts like this brghietn up my day. Thanks for taking the time.
  • # pauRYSXfameMOA
    http://crorkz.com/
    Posted @ 2014/08/04 3:39
    r9ZYVw Thanks again for the blog. Really Great.
  • # EFCYZseCHNjlPsRQ
    http://alarmassecurity.es/alarmas
    Posted @ 2014/08/09 2:01
    Really informative blog article.Thanks Again. Really Great.
  • # Oszsl Fge Auxl Ctz Ksupjy
    Thomasea
    Posted @ 2014/12/05 3:48
    consistently over the last 10 years, as the People from france cuff has been the most esteemed type of t-shirt. The more expensive cufflinks at any time offered were a couple provided to the soon-to-be King Edward VIII by means of his afterwards girlfriend Wallis Simpson. These kind of highlighted gemstones placed in gold as well as displayed market forsplendid present of style and know-how can harmonize having almost any costume, elegant or perhaps laid-back, in this article an essential function untouched within Clair viewpoint associated with simpleness, some sort of cufflink for everyone instances.

    http://www.hiigroup.com/files/201412315314472050.html
    http://www.abcinc-us.com/files/201412315202881362.html
    http://www.westerneliteins.com/files/201412315145524757.html
    http://www.drraebanigan.com/files/20141231533466694.html
    http://www.ndoes.org/files/201412315261496755.html
    http://www.lawofsea.com/files/201412315163993410.html
    http://www.ecci7000.com/files/201412315162625632.html
    http://www.sanclementeatdavenport.com/files/201412315101136349.html
    http://www.midcoastplanning.org/files/201412315125795911.html
    http://www.downriverarts.org/image/20141231575783828.html
    http://www.twinmarblegranite.com/acc/20141221742948921.html
    http://www.universityofiron.org/acc/201412217515573315.html
    http://www.texascharityadvocates.org/acc/201412217483939231.html
    http://www.toykingdomllc.com/acc/201412217452117532.html
    http://www.thelocksmith-inc.com/acc/201412217483048414.html
    http://www.rochet.com/files/201412215432497351.html
    http://www.linear-guideways.com/files/20141221555974077.html
    http://www.andersonpaddles.com/files/2014122162136297.html
    http://www.rochet.com/files/201412215454086266.html
    http://www.iccworld.com/files/201412215311517753.html
  • # elEaXHEusudmqxnOEC
    sally
    Posted @ 2015/04/17 20:15
    n21ElY http://www.FyLitCl7Pf7kjQdDUOLQOuaxTXbj5iNG.com
タイトル  
名前  
Url
コメント