Javaの復習をしました。

先週のありえる勉強会でわからないことが多かったので調べました。自分用メモです。
年々Java屋から遠ざかっています…


エスケープ分析」と「強参照・ソフト参照・弱参照・ファントム参照」についてです。

エスケープ分析(Escape Analysis)

ヒープ領域にオブジェクトを保持すると、ガベージコレクションの対象になるので、そのブロック中でしか使わないと分かっているものに対してはスタック上に保持した方がいいよね、という発想から来ている最適化方法。


Java SE 6からJVMに実装されているようです。

 -XX:+DoEscapeAnalysisオプションを付けることでエスケープ分析を指示できるようです。

そもそも「エスケープ」とは何か

IBM Developer Worksの記事「Javaの理論と実践: パフォーマンスに関する都市伝説を再検証する」では、エスケープ分析のエスケープとは漏洩と訳されています。
「オブジェクトの参照がヒープに保存されたり他のオブジェクトから保持される可能性があること」を指すそうです。
このエスケープがあるかないかをJVMが判定するのが「エスケープ分析」。
エスケープがなければ、そのオブジェクトはそのブロック中でしか有効でないのでスタック上にメモリを確保したり、そもそも最適化によって除去できるという仕組みです。


しかし、このIBM Dev Worksの記事わかりやすいです…。良く読むと。
てか2005年の記事なんですね。ずいぶん昔からあるもんだ。

先のIBMの記事でわからんことメモ(教えて誰かさん)
  • オブジェクトの状態が変わらないこともエスケープしているかどうかの要件なの?

getDistanceFrom() はotherコンポーネントの状態を決して変更しないことが

エスケープ分析に掛かっている節なのかがよく分からないです…。
別にotherの状態が変わろうが変わるまいがotherLocationがエスケープしていないことは変わらないのでは?


もしかして次のパラグラフで「全フィールドがパブリックの場合に得られるパフォーマンスと、全く同じパフォーマンスが得られる」状態が待っているので、otherのメソッド呼び出しがない状態になっていることを説明しているのでしょうか?


後で調べよう(調べなさそうですが…)

ついでに読みました

ダイナミック・デオプティマイゼーションとかJVM頭良すぎる。


昔から言われているように現在のコンパイラがある最適化実装をしているからといってそれが効くようにコーディングするのはアホですね。
どうしてもやらざるを得ない場合があるのはわかりますが。

ファントム参照

そもそも参照に色々あるのが昔からわかってなかった。というか分かる努力とかしてなかった。

参照の種類
  1. 強参照:普通の参照。フィールドに非プリミティブ型で持っている関係。
  2. ソフト参照
  3. 弱参照:WeekHashMapの実装とかに使われているヤツ。
  4. ファントム参照


強参照は普通の参照なのでみんな意識せずに使っているものです。
問題はソフト参照以下3つ。参照オブジェクトを生成して使います。


自前でサンプル作ったりして調べようかと思ったけどほとんど書いてあるサイトがありましたので、読んで理解しました。
知の高速道路だなーと思いつつ手を動かさないので結局スキルアップはせず…

ソフト参照、弱参照

強参照は、参照先のオブジェクトが必ずあることが保証されていますが、ソフト参照・弱参照を介した場合、オブジェクトがガベコレされている可能性があります。
普通のJava使いは上記の文章の前半から何を当たり前なことを、と思うかもしれません。
そして後半には何言ってんじゃNullPointerExceptionでるやろ!と怒るかもしれません。


ソフト参照・弱参照はそういうものです。


使いどころとしてはキャッシュ等。
メモリに余裕があるときはキャッシュサイズが多くてもいいけどメモリに余裕がなくなってきたらキャッシュしている場合じゃなくなります。
そんなとき黙ってそっと場所を譲る。そんな謙虚な仕組みです。


ソフト参照と弱参照の違いは、ガベージコレクタの判断基準のレベルの違いらしいです。
Javadocをいくら読んでもニュアンスが細かすぎて正確に分かってないかも)


ソフト参照はメモリギリギリまで保持する可能性がある(正確にはOutOfMemoryが発生するまえには全部解放されている、なのでメモリに余裕があるときにすぐ解放してしまっても仕様通り)のに対し、弱参照は割とサクッと持ってかれる可能性があるという違い。かと。


IBM Developer Worksの記事に書いてありましたよ。なんでも書いてあるなぁ

「ソフト参照でメモリー・リークを塞ぐ」の方から引用

あるオブジェクトに対して残っている参照が、弱参照あるいはソフト参照のみである場合、そのオブジェクトは『ソフト到達可能(softly reachable)』と言われます。ガーベジ・コレクターは、弱到達可能(weakly reachable)オブジェクトを収集するほど積極的には、ソフト到達可能オブジェクトを収集しません。ガーベジ・コレクターは、本当にメモリーを「必要とする」場合のみ、ソフト到達可能オブジェクトを収集するのです。ソフト参照は、ガーベジ・コレクターに対して、「メモリーが非常に不足しているのでない限り、私はこのオブジェクトを保持しておきたい。しかしメモリーが非常に不足しているのであれば、どうぞ収集してください。私はそれに応じて何とかします」と言うための方法なのです。

なるほどー。でも実装は同じJVMもあるとか。

ファントム参照

これはなんというか参照とかなのかよくわかりません。
ソフト参照・弱参照は、キャッシュとして使われる場合も有るとおり、参照をもう一度使いたいと思ったら参照オブジェクトから実オブジェクトを引っ張ってきて(getメソッド)、強参照に戻すことができます。


ファントム参照は戻せません。
ファントム参照に預けたオブジェクトへの強参照が切れたら死んだも同然です。ゾンビです。
このゾンビをガベコレで解放する(ファイナライズはされてる)タイミングを、ファントム参照オブジェクト自体の参照が切れたときにコントロールできるのがファントム参照の存在意義らしいです。
(ホントかちょっと怪しい…)


ちなみに参照キュー(ReferenceQueue)の扱いがソフト参照・弱参照とファントム参照ではちょっと違うので注意。ややこしい。
さらに、ファントム参照されているオブジェクトはファントム参照オブジェクト自体がガベコレされるかファントム参照から明示的にクリアされるかしないとヒープから解放されないので注意。

ソフト参照および弱参照と違って、ファントム参照はそれらがキューに入れられるときにガベージコレクタによって自動的にクリアされません。ファントム参照を介して到達可能なオブジェクトは、すべてのファントム参照がクリアされるか、ファントム参照自身が到達不可能になるまで到達可能です。


そういえばクラスローダ関連もよくわかってないのでいつか勉強ないとです…