クラスを使うことが推奨されているのでこちらもざっくりとみてみます。クラスCleanerCleanerは、一連のオブジェクト参照と対応するクリーニング・アクションを管理します。クリーナは、オブジェクトが有線で到達可能になったことがクリーナに通知された後で実行するために、クリーニング動作はregisteredです。クリーナは、PhantomReferenceとReferenceQueueを使用して、reachabilityが変更されたときに通知を受け取ります。各クリーナは、独立して動作し、保留中のクリーニング動作を管理し、クリーナがすでに使用されていないときにスレッドおよび終了を処理します。オブジェクト参照と対応するクリーニング・アクションを登録すると、Cleanableが返されます。効率的な使用法は、オブジェクトが閉じられたり不要になったときに、cleanメソッドを明示的に呼び出すことです。クリーニング・アクションは、すでに明示的にクリーニングされていない限り、オブジェクトがファントム到達可能になったときに呼び出されるRunnableです。クリーニング動作は、登録されているオブジェクトを参照してはならないことに注意してください。あれば、オブジェクトは想像を絶するものにならず、クリーニング動作は自動的に呼び出されません。クリーニング・アクションの実行は、クリーナに関連するスレッドによって実行されます。クリーニング・アクションによってスローされたすべての例外は無視されます。クリーナおよびその他のクリーニング・アクションは、クリーニング・アクションの例外の影響を受けません。スレッドは、登録されているすべてのクリーニング処理が完了し、クリーナ自体がガベージ・コレクタによって再利用されるまで実行されます。System.exit中のクリーナの動作は実装固有です。クリーニング動作の呼び出しの有無は保証されていません。ほかで指定がない場合、null引数をコンストラクタまたはこのクラスのメソッドへ渡すと、NullPointerExceptionがスローされます。ネストされたクラスが一つあります。Cleaner.CleanableCleanableは、Cleanerに登録されているオブジェクトとクリーニング・アクションを表します。ネストされたクラスにメソッドが一つだけあります。clean()クリーニング可能なものの登録を解除し、クリーニング動作を呼び出します。クリーニング可能なクリーニング動作は、cleanの呼び出し回数に関係なく、最大で1回呼び出されます。クラスにはメソッドが3個あります。create()新しいCleanerを返します。threadを作成します。loaderに設定されます。setの場合にのみ実行されます。ファントムに到達し、登録されたすべてのクリーニング動作が完了すると、クリーナは終了します。現在のスレッドがスレッドの作成または開始を許可されていない場合。threadFactory)ThreadFactoryからThreadを使用して新しいCleanerを返します。threadに設定され、ファントム到達可能オブジェクトを処理し、クリーン・アクションを起動します。factoryは、クリーニング・アクションを実行するのに適したスレッドを提供する必要があります。ファントムに到達し、登録されたすべてのクリーニング動作が完了すると、クリーナは終了します。現在のスレッドがスレッドの作成または開始を許可されていない場合。action)オブジェクトにファントム到達可能になったときに実行するオブジェクトとクリーニング・アクションを登録します。クリーニング動作の動作については、上記の「APIノート」を参照してください。ドキュメントから学んだ。挿入はガーベジ・コレクトと非同期で行われます。働いてすぐに挿入されると考えてはいけないようです。入れられたオブジェクトを取り出してクリーンアップする。クラスを使ってクリーンアップする方法もあります。クリーンアップの際はリソースの解放処理が必要であれば必ず実行するようにしておくのが無難かもしれない。理解できているかは怪しいけどプログラムを組んでみることにする。バージョンとしてみよう。クラスを使ったものに変更してみる。そんなこんなで次のようなプログラムを組んでみました。メソッドをオーバーライドして利用しています。必要ではありませんでした。メソッドはコメントアウトして実行できないようにしてあります。プログラムは途中で止まってしまいます。プログラムの実行結果は次のようになります。665957秒ほどで終了しました。プロファイラで確認してみます。メソッドを使うように変更した実行結果は次のようになりました。656656秒で終了しました。メソッドを使ったのとほぼ同じですね。プログラムは途中で止まってしまいます。プログラムで止まることはありません。プロファイラで確認します。大きな違いはなさそうです。利用したプログラムを実行してみます。クラスを使ったものも試してみます。プログラムの実行結果は次のようになりました。015秒で終了しました。ガーベジ・コレクタ優秀ですね。プロファイラで覗いてみます。メソッドを使うように変更して実行してみます。プログラムの実行結果は次のようになります。0これも15秒で終了しました。プロファイラで覗いてみます。こちらのほうが僅かだけど良いかもしれない。違いはガーベジ・コレクタが変更されたくらいだと思うのですけど他にも何か変更があるのかもしれません。スレッドを確認してみます。メソッドを使用した場合です。いう見慣れないスレッドがありますね。これがパフォーマンスアップの要因の一つなのかな。関連のことはあまり気にしたことないのでよく解りません。メソッド両方ともコメントアウトして無効にして実行してみました。プログラムは15秒で終了しました。二回必要だったのに・・・ガーベジ・コレクタ凄く賢くなっている。使い方を間違ってるかもしれない)このあたりのことを調べ出すとガーベジ・コレクタ沼にはまって苦しむことになるので誰か親切な人が詳しく解りやすい解説記事をネット上にアップしてくれるのを待つことにする。クラスもファイナライザ同様にあまり使うのを好ましく思われていません。クラスを使ってみます。以降の新しいものを使うことを前提にして組み直しました。生成、31行目でファントム到達可能になったときに実行するオブジェクトとクリーニング・アクションを登録します。無駄なことをしています。メソッド内のゴニョゴニョしたコードは無くて空でも問題無いです。あっても無くてもほぼ変わりはありません。(少しは変わるかもと思って試しただけです)たったこれだけです!非常に便利です。これでファイナライザ攻撃の心配はなくなります。プログラムの実行結果は次のようになります。016秒で終了しました。クラス使うと便利ですね。ファントム到達可能になったときに実行するオブジェクトとクリーニング・アクションを登録するだけだし、それにクリーニング・アクション用の専用スレッドが起動される。ファイナライザを使って何かしようとすると自前でスレッドを用意したりしなくちゃいけない場合がある。ファイナライザ攻撃によるセキュリティ上の問題も無い。ファイナライザを使う必要は無いような気がする。近い将来使えなくなるしね。そもそもファントム到達オブジェクトって強参照、ソフト参照、弱参照のどれから辿っても到達できなくなってファイナライザ呼び出しが完了した状態ってところで使いどころが限定されそうな気がする。常時返すようになっている。対象ってことですよね。だめだ、頭痛が痛くなりそうだ。(まさに今こんな感じです。ただのクリーンアップ用にしか思えなくなってきた。パフォーマンスアップや使い勝手が良くなるのはいいけど解りやすい情報が乏しいのはなんとかしてほしい。エントリーの続きです。どんなものなのか調べてみます。APIドキュメントには次のように記されてます。弱参照オブジェクトです。弱参照オブジェクトは、その弱参照オブジェクトのリファレントがファイナライズ可能になり、ファイナライズされ、そして再生されることを阻止することはありません。弱参照は、ほとんどの場合で正規化マッピングを実装するために使用されます。ある時点で、オブジェクトが弱到達可能であると、ガベージ・コレクタが判断したとします。その時点で、ガベージ・コレクタは、そのオブジェクトへの弱参照すべてと、強参照およびソフト参照のチェーンを経由してそのオブジェクトに到達できるような、ほかの弱到達可能なオブジェクトへの弱参照すべてを、原子的にクリアします。同時に、ガベージ・コレクタは以前に弱到達可能なオブジェクトがすべてファイナライズ可能であることを宣言します。同時にまたはあとで、ガベージ・コレクタは、参照キューに登録されているそれらの新しくクリアされた弱参照をキューに入れます。働くときに無条件で参照を解放されるってことかな。ように参照の使用頻度やヒープの状況を考慮して参照を解放するのとは大違いですね。クラスにはコンストラクタが二つあります。referent)指定されたオブジェクトを参照する、新しい弱参照を作成します。新しい参照は、どのキューにも登録されません。q)指定されたオブジェクトを参照し、指定されたキューに登録されている新しい弱参照を作成します。参照が登録されるキュー。登録が必要ない場合はnullメソッドは無いですね。それではプログラムを組んで試してみます。前回組んだプログラムと同じように無駄にメモリーを消費するインスタンスを1000個作っているだけです。メソッドを実装しました。それによって何かするわけでなく呼ばれたことを確認するためだけです。---");}}}プログラムの実行結果は次のようになりました。プログラムの処理時間も15秒と非常に短い時間です。累積時間もぜんぜん違います。プロファイラで確認してみます。タイムも雲泥の差がある。使いたくないと思ってしまう。スローする前にクリアされていることが保証されている。メモリの容量に応じてスケールするキャッシュ用って感じかな。弱参照オブジェクトが弱到達可能になったらガベージ・コレクタでクリアしたい時に使う(キャッシュしない)。ドキュメントの文章が難しく書かれているのであまり自信はないけどこのような違いがあるようだ。プログラムの実行結果からもその様子が少しは解ります。違いはプログラムの出力結果のガベージ・コレクタの動作ではっきりと解ります。スローしないところまで回収されないようです。0なかなか面白い仕組みになっていますね。強参照しか普段使わない私にとって新鮮な気分です。