2

いくつかのテストを実行するために、SoftReferenceのオブジェクトのキャッシュに保存したオブジェクトの一部またはすべてが破棄されたときにアプリケーションがどのように動作するかを確認したいと思います。

これを行うために、キャッシュされたSoftReferenceオブジェクトに格納されている参照を手動でクリアしたいと思います-これらのオブジェクトのVM処理をシミュレートします-ただし、現在そのオブジェクトへの強い参照を持っているものが他にない場合に限ります(これは次の場合に当てはまります)。別のプロセスが最近、参照されたオブジェクトをキャッシュから取得しました)。

私のアプリケーションはシングルスレッドなので、このコードの実行中にキャッシュされたオブジェクトのソフト到達可能性が変化することを心配する必要はありません。これはまた、私が現在ロックメカニズムを持っていないことを意味します-もし持っていれば、オブジェクトが「使用されている」かどうか、したがって強く到達可能かどうかを判断するためにこれらを使用できた可能性がありますが、残念ながら私は必要ありませんそのようなロックの。

私が試した1つのアプローチは、ReferenceQueueに登録されているキャッシュに格納されているすべてのオブジェクトに追加のSoftReferenceを作成することです。そうすることで、キャッシュ内のソフトに到達可能なすべてのオブジェクトに追加のSoftReferenceがキューに追加されることを期待していました。そのため、キューをループして、それらのオブジェクトをキャッシュから削除するだけでした。ただし、GCは、ソフトリーチ可能なオブジェクトをそれぞれのキューに自由にエンキューしているようです。そのため、キャッシュ内のオブジェクトの反復処理が終了すると、キューに何かが追加される保証はありません。

私も見てきたことの1つは、値が非常に小さい-XX:SoftRefLRUPolicyMSPerMBJVMオプションです。賢明なメモリ割り当てを使用すると、ソフトに到達可能なオブジェクトがソフトに到達できる瞬間に、キャッシュからソフトに到達可能なオブジェクトがクリアされる可能性がありますが、キャッシュからソフトに到達可能なオブジェクトをクリアするリクエストを受け取るまで、アプリを正常に実行したいと思います。 。JVMオプションとして、アプリの実行中にこの値を変更できるとは思いません。

それで、オブジェクトがソフトにしか到達できない(したがってクリアできる)かどうかを私がどのように判断できるかについて誰かが何か考えを持っていますか?

編集:明確ではなかったかもしれないいくつかの追加のポイント:

  • これらのソフト参照オブジェクトをクリアしたいときに、アプリはおそらく便利な作業を行うでしょう。ですから、GCにオブジェクトをクリアさせようとしないほうがいいと思います。
  • どのソフトに到達可能なオブジェクトをクリアするかを選択できれば望ましいでしょう。
  • アプリを正常に実行したい、つまり本番メモリ設定を使用したい。コードの設定を変更すると、本番環境の値にリセットできますが、問題ありません。
4

3 に答える 3

1

IIRC、ソフト参照は(ある意味で)OutOfMemoryErrorスローされる前にクリアされることが保証されています。したがって、大量のメモリを割り当てる場合、オブジェクトが強く参照されていなければ、それらはクリアされるはずです。(未検証。)

于 2009-05-15T11:46:15.417 に答える
0

テスト中は、現在のソフト参照システムを弱参照システムに置き換えてください。

弱参照システムは、jvmがガベージコレクションを実行するのを待つ代わりに、他の着信参照がないオブジェクトを、それが発生するとすぐに削除します。

于 2009-05-15T12:03:56.560 に答える
0

いくつかの答えを混ぜる:Tom Hawtinが言ったように、たとえば次のコードを使用して、outOfMemoryになるまでメモリを割り当てます。

private void doOutOfMemory() {
    try {
        List<byte[]> list = new ArrayList<byte[]>();
        while (true) {
            list.add(new byte[200 * 1024 * 1024]);
        }
    } catch (OutOfMemoryError ex) {
    }
}

クリアするオブジェクトを制御したくない場合は、保持するオブジェクトを強く参照してください。

代わりにweakReferencesを使用して、System.gc()を呼び出すだけで、それらが常にクリアされる保証はないことをクリアすることもできます...

于 2009-05-15T14:13:01.087 に答える