複雑な実行の前にアイドル状態のときにヒープで 23 MB を使用する Java アプリケーションがあり、TaskManager の java.exe プロセス サイズは約 194 MB でした。いくつかの複雑な操作の後、java.exe のサイズは約 500MB まで増加し、ヒープ サイズも増加しました。System.gc() メソッドを呼び出すことにより、数回のフル GC の後、ヒープ サイズが 23MB に減少します。しかし、java.exe のサイズは約 600MB から約 237MB に減少し、まだ約 43 MB のデータが含まれています。これを減らす方法はありますか?それとも何かの癖によるものですか?
2 に答える
これは正常です、心配しないでください。JVM は、複雑なロジックを実行する必要があるときにメモリを取得します。Java がタスクの処理を完了すると、JVM は引き続きそのメモリを予約済みスペースとして保持し、OS に解放されません。JMV は基礎となる OS から同じメモリを再度要求する必要がないため、このアーキテクチャはパフォーマンスに役立ちます。-Xmx JVM パラメータで定義した範囲内に収まります。
興味深い詳細については、この IBM リンクを参照してください。http://www-01.ibm.com/support/docview.wss?uid=swg21326774
残念ながら、これは JVM のあいまいな領域の 1 つです。OS と JVM が相互にメモリを共有する方法については、実際にはあまり制御できません。JVM は、実行にいくらかのメモリを必要とする仮想 OS と考えてください。親 OS と VM の両方がリソースを必要としており、取得したリソースにできるだけ多くのメモリを保持したいと考えています。OS に追加のメモリを要求するのは時間のかかる操作であるため、ほとんどの JVMはメモリが不要になった場合でも OS にメモリを解放しません。
内部 JVM メモリ管理の詳細については、Oracle のこのホワイト ペーパーを参照してください。http://www.oracle.com/technetwork/java/javase/memorymanagement-whitepaper-150215.pdf
最初に IBM のリンクを読んでから、ホワイト ペーパーで説明されている奇妙なメモリの世界を掘り下げることをお勧めします。これらのリンクはどちらも非常に有益で興味深いものです。
Java プロセスの OS フットプリントは、
- Java ヒープ (サイズは によって制限されます
-Xmx
) - Java クラス関連のメタデータ (または HotSpot JVM での永続的な生成)
- NIO 経由でアクセス可能な非ヒープ メモリ
- Java スレッドのスタック領域
ガベージ コレクション アルゴリズムには、空きメモリを OS に返すものと返さないものがあります。HotSpot JVM では、シリアルの古いスペース コレクター (通常はデフォルトで有効になっています) がメモリを OS に戻しています (プロセスの縮小を確認できます)。-XX:+UseParallelOldGC
ただし、またはなどの他のコレクターは、-XX:+UseConcMarkSweepGC
未使用のヒープ メモリを OS に返すことはありません。
HotSpot JVM には、上記のすべてのメモリ領域を管理/制限するオプションがあります。メモリのサイジングと GC チューニングに関連する JVM オプションの包括的なリストは、私のブログにあります。