Android らしい Java - 2. 寿命
寿命、ライフサイクルのはなし。(Part.1 はここ)
Android の中には、決められた寿命を持つ重要なオブジェクトがいくつもある。代表例は Activity. View も Fragment もプラットホームによって寿命が決められている。
Java は誰かに決められた寿命を扱うのがあまり得意でない。多くのオブジェクトは Java 自身の GC が寿命を決める。GC があるからプログラマは寿命について悩まなくていい。そんな態度が従来の Java にはある。C++ のように神経質な寿命管理は出番が少ない。
Java でも File のような OS の資源は GC でなくプログラマが寿命を決める。Socket なんかはもう一段厄介で、相手側から閉じられると勝手に死んでしまう。そして死んだオブジェクトを触るコードは呪いの例外に見舞われる。
勝手に死ぬ Activity や View の性質は Socket に近い。でもそれがコードの中心にあるぶん禍々しい。従来の Java はこうした外側の寿命と戦う武器を持っていなかった。頼みの綱たるはずの AutoCloseable も非同期性相手には歯が立たない。
死の定めと向き合わないまま従来の Java の流儀で書かれたコードは寿命を扱う正しさに確証が持てず、クラッシュログに引きずられたアドホックで防衛的なチェックを撒き散らかす羽目になる。
非同期性と突然死の世界でどうコードを書くか。オブジェクトが死んだ瞬間に紐付いた処理をすべてキャンセルし、誰かが死体を目にする可能性を摘み取る。これが Android らしい Java の今のところの答えだと自分は理解している。RxJava もキャンセルの仕組みを持っている。ゾンビに出会ってやるべきことは防衛的チェックではなくキャンセル漏れ探し。銃撃戦ではなく葬儀。
死体に出くわす問題の対にあるのが、手の届かない亡骸を埋葬しそこねるメモリリーク。従来の Java にもあった問題だけれど、プロセスの実行時間の長さや非同期性に伴う無名クラスの多用が被害を大きくしている。寿命の節目で正しく供養しつつ LeakCanary などのツールでこまめに漏れチェックをするのが今のところの解らしい。C++ かよ、とぼやきたくなる。
キャンセル忘れもメモリリークも、現行の答えはいまひとつ決定打に思えない。もう少しイディオムが固まったら宣言的なアノテーションと AutoValue のようなコード生成で素敵な感じに助けて欲しい。甘い期待を抱いている。