読者です 読者をやめる 読者になる 読者になる

Webエンジニア susumuis の技術ブログ

このブログの内容は個人の見解であり、所属する組織の公式見解ではありません

sun.misc.Unsafeを使う

コンストラクタを呼ばないでインスタンスを生成してリフレクションで横から強制的に初期化という行為が必要だった。sun.misc.UnsafeというAPIを使用するとできるらしいのでやってみた。あっけなく出来てしまった。まずは今回テストしたコードを下記に貼り付けます。

 

実行すると延々と、"hello, hoge"と出力されます。

このクラスはコンストラクタを呼ぶと例外を飛ばす酷いやつですが、ちゃんとインスタンス化できていることがわかります。

 

コードUnsafeインスタンスの取得がリフレクション経由になっていますが、どうやら、この取り方が自分が調べた限り主流のようです。

理由は

  • Unsafeオブジェクトはprivateコンストラクタなのでインスタンス化できない
  • Unsafe.getUnsafe()メソッドはセキュリティ制御されていて、trustedなクラスからしか使用できない
  • けど、そいつのインスタンスはUnsafeクラスのstaticインスタンス theUnsafe に格納されているから、リフレクションで「盗む」ことができる

ということみたいです。

詳しくは http://mishadoff.github.io/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/

 

無限ループにしたのは、Unsafeという名前にビビったので、まさかメモリ管理されないとかないか、調べるためです。

実行させたまま、jvisualvmででヒープ情報を見たところ右肩上がりにはなっていないことがわかります。

結果は次の通り

なお、この結果は環境に依存するものですので、他の方の環境では同じ結果になるとは限りませんのでご了承下さい。

 

Java7

f:id:s-ishigami:20140331102547p:plain

 

Java8

f:id:s-ishigami:20140331103427p:plain

Java5

f:id:s-ishigami:20140331100738p:plain

念の為に、heap dumpも取っていましたがUnsafeTestのインスタンス数は0となっていましたので、確かにGCされているようです。