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