1

JDK 1.6 で実行されている Java アプリケーションでヒープ サイズの使用をテストしています。ツール VisualVM を使用して、ヒープの使用状況を監視します。数分間、最大ヒープ サイズの使用量が約 500 MB であることがわかりました。System.gc() を呼び出すオプション「Perform GC」を使用しました。初めて使用したとき、最大ヒープは 410MB に減少し、もう一度使用して 130MB を取得し、次回は 85MB にしました。間隔を空けずに、次から次へと4回すべての呼び出しを行いました。System.gc() の呼び出しで最初にすべてのヒープが 85MB に収集されないのはなぜですか。この背後に他の理由がありますか。または、他の方法を試す必要がありますか?

4

3 に答える 3

2

System.gc() は、すべてのオブジェクトが 1 回スキャンされると戻ります。

オブジェクトは、収集後に finalized() する必要があります。ほとんどのオブジェクトはこのメソッドを実装していませんが、実装しているオブジェクトについては、後でクリーンアップするためにキューに追加されます。これは、これらのオブジェクトをまだクリーンアップできないことを意味します (オブジェクトを保持するキューノードではありません)。つまり、GC をトリガーする行為により、メモリ消費が一時的に増加する可能性があります。

さらに、GC によってクリーンアップされる場合とされない場合があるオブジェクトへの SoftReferences があります。他の多くがクリーンアップされていない場合にのみ、これらをクリーンアップする必要があるという前提があります。

つまり、すべてのオブジェクトを 1 サイクルでクリーンアップできるわけではありません。

于 2013-05-17T07:15:23.260 に答える
0

考えられる理由の 1 つは、java.lang.ref.Reference型の使用である可能性があります。GC が「参照」を壊そうとする場合、これは GC が適切に完了した後に発生します。結果として到達不能になったオブジェクトは、次の GC サイクルで処理するために残されます。

ファイナライズも同じように機能します。オブジェクトにファイナライズが必要な場合、そのオブジェクトとそこから到達可能なすべてのオブジェクト (のみ) は、次の GC サイクルでのみ収集可能になる可能性があります。

次に、ヒープを縮小するための GC のアルゴリズムが非積極的であるという問題があります。Java HotSpot VM Optionsページによると、ガベージ コレクション後に 70% 以上が空いている場合にのみ、GC はヒープを縮小します。ただし、これが完全な GC を指しているかどうかは完全には明らかではありません。したがって、GC で部分的な GC を実行して縮小し、次に完全な GC でさらに縮小することができます。

(Javadoc の文言から、System.gc()完全な GC を実行すると推測する人もいます。ただし、これは実際にはバージョン/GC に依存していると思われます。)


しかし、正直に言うと、これはすべて議論の余地があるはずです。できるだけ多くのメモリを返すようにアプリケーションを強制しようとしても無意味です。キャッシュされたデータを破棄するように強制している可能性があります。アプリケーションが再びアクティブになると、キャッシュのリロードが開始されます。

于 2013-05-17T07:18:09.510 に答える