【新機能】作り忘れたまとめはありませんか?31日前まで期間指定してまとめが作れる高度な検索ができました。有料APIだからツイートの漏れはありません!

JAVA(Android)のメモリ管理

@akisutesama さんのJAVAのメモリ管理を理解する行程が非常にいいと感じたので、残しておきます。
プログラミング Android java
14183view 4コメント
20
ログインして広告を非表示にする
akisute/Masashi Ono @akisutesama 2011-09-18 16:09:41
まずiOS(Cocoa Touch, Objective-C)とWindows(Silverlight/WinRT, C#)の場合を考える。iOSの場合はdelegate, KVO, NSNotificationCenterがある。
akisute/Masashi Ono @akisutesama 2011-09-18 16:10:53
Windowsの場合はC#であればdelegateとそれをさらに拡張したeventの仕組みで一発解決する。これが一対一と一対多を兼ねる。参照先をweak referenceするから循環参照の危険もない。
akisute/Masashi Ono @akisutesama 2011-09-18 16:12:23
多対多はどうすればいいのか正直わからないのだが、そういう仕組みがあるらしいということは聞いている。最も、たいていの場合は一対多で事足りるけど。
akisute/Masashi Ono @akisutesama 2011-09-18 16:13:12
最後に問題のJavaだ。Androidを想定する。一対一の場合はInterfaceとそれを継承したクラスのインスタンスを渡すことで通知を行うのがほぼ通例だ。一対多は全くわからない。多対多もさっぱりだ。
akisute/Masashi Ono @akisutesama 2011-09-18 16:15:10
一対多と多対多は後ほど考えるとして、まず一対一。さっきのInterfaceとそれを継承したインスタンス渡しというのはiOSのdelegateの実装と基本同じである。問題はそこにメモリの話が付いてくる。iOSにはweak referenceがある。しかしAndroidの場合は?
akisute/Masashi Ono @akisutesama 2011-09-18 16:16:35
当然Javaにもweak referenceはある。java.lang.ref.WeakReference<T>がそれだ。きちんとそれを使って構築されているのだろうか。
akisute/Masashi Ono @akisutesama 2011-09-18 16:18:17
さらに問題になるのが、そういうdelegateがweak referenceとして渡したインスタンスを保持しているのか、それとも保持していない(すぐに使って捨てる)のかが明示的になっているケースが見当たらない(俺調べ)という点だ。iOSの場合はweak referenceが自明。
akisute/Masashi Ono @akisutesama 2011-09-18 16:19:08
weak referenceなら自分がそのインスタンスを責任持って抱えないと(抱える仕組みを使わないと)GCされて死ぬ。そうでないなら自分が責任持ってそのインスタンスを使用後破棄しないとメモリリークして死ぬ(気がする。gcが循環参照を綺麗に捨ててくれるなら別)。
kishikawa katsumi @k_katsumi 2011-09-18 16:20:04
@akisutesama Androidは参照カウンタじゃないからそこが循環参照してても別にいいんじゃないの?ダメなのですか?
akisute/Masashi Ono @akisutesama 2011-09-18 16:21:24
というメモリ周りの話がまるで表に出てきて見えないのがJavaのすげぇ困ったところなのである。そこで質問。JVMは循環参照してても全然問題なくgcしてくれるから気にしないで通常の強参照(フィールド)に突っ込んじゃって全然OKなのか、否か。この程度のこともわからん程度すすんません><
akisute/Masashi Ono @akisutesama 2011-09-18 16:22:33
ここで、もし答えが「大丈夫だ、問題ない」であったとしても、だ。強参照同士で相互ループしているだけならいい。それら両方が死んだら死ぬのだから。しかしもし万が一何かの間違いでほぼ永続するインスタンスからそれらのどちらかが強参照されてしまったら?・・・死亡確定。ってこれはどこでも同じか
akisute/Masashi Ono @akisutesama 2011-09-18 16:23:00
書いてたらなんか大丈夫そうってことがわかってきた。JVMすげぇ。やべぇ。
akisute/Masashi Ono @akisutesama 2011-09-18 16:24:12
Effective Javaを読んでみよう。
kishikawa katsumi @k_katsumi 2011-09-18 16:28:03
@akisutesama いや、Androidで例外はあるのかもしれないけど、循環参照しててもルートから辿れないオブジェクトはGCのタイミングで破棄されるよ。JVMっていうかGCのアルゴリズムの話かな。
akisute/Masashi Ono @akisutesama 2011-09-18 16:28:39
@k_katsumi ですよねぇ。うん。大丈夫だ。参照カウントじゃないからすげー頭いい。
akisute/Masashi Ono @akisutesama 2011-09-18 16:28:56
あと、匿名クラスのインスタンスとか、内部クラスとかstatic内部クラスとかのメモリの絡みが一マイクロメートルもわからん。俺の情弱認識では、内部クラスは親クラスのインスタンスに対して強参照を持っている。匿名クラスは匿名クラスを生成したクラスが内部クラスを作ったのと同じ状態になる。
hiratara @hiratara 2011-09-18 16:30:40
@akisutesama Javaはリファレンスカウンタ方式じゃないので大丈夫ですよ。リファレンスカウンタだと循環参照だと解放しても0にならないって問題がおきますが、JavaのGCはルート集合から辿れない物は全て破棄なんで、循環してても関係ないです。
akisute/Masashi Ono @akisutesama 2011-09-18 16:32:20
ということでまとめ。Javaの場合は強参照とか気にする必要がありません。インスタンス渡せばおk。たとえ相互参照していてもgc様が綺麗に解決してくれますひゃっほう。やったねたえちゃん!
akisute/Masashi Ono @akisutesama 2011-09-18 16:32:46
とか考えながらjava.lang.refを見ていたらWeakの他にSoftとかPhantomとかあった。どういうことなの・・・
akisute/Masashi Ono @akisutesama 2011-09-18 16:35:32
Effective Javaはお作法の本であってメモリ関連のお話はしてくれないのでありました。ガハァ。
akisute/Masashi Ono @akisutesama 2011-09-18 16:36:53
こんなとき佐藤太一がいてくれれば・・・「JVMのソース嫁」とアドバイスをしてくれるものを・・・
残りを読む(69)

コメント

akisute/Masashi Ono @akisutesama 2011-09-18 19:02:48
ほそく。 「Javaの内部クラスが外部クラスのインスタンスを共有している」といったのは以下を見て。 http://blog.zenbo.jp/article/14783904.html http://blogs.wankuma.com/nagise/archive/2007/07/31/88042.aspx 確認取ってないので実際はどうかよくわかりません(佐藤太一あたりが出てくると殺されてしまう><)けどだいたいあってそうな気がしたのでまぁいいかなと。それともやっぱり内部クラスは外側クラスのインスタンス
akisute/Masashi Ono @akisutesama 2011-09-18 19:10:13
ということでasync-awaitにも制約はあるよーでもらくだよーってお話。WinRTでの非同期処理は基本全部これみたい(これは情報源無し、すんません><)。すばらしー。
ログインして広告を非表示にする
ログインして広告を非表示にする