web-dev-qa-db-ja.com

使用していないときにJavaヒープを下げる方法はありますか?

私は現在Java=アプリケーションに取り組んでおり、そのメモリ使用量を最適化するために取り組んでいます。私が知る限り、適切なガベージコレクションのガイドラインに従っています。しかし、ヒープは必要ありませんが、最大サイズのままです。

私のプログラムは、コンピュータが人によって使用されていないときに、1時間に1回、リソースを集中的に使用するタスクを実行しています。このタスクは適切なメモリチャンクを使用しますが、タスクが完了するとすぐにすべてを解放します。 NetBeansプロファイラにより、メモリ使用量は次のようになることがわかります。

Java program memory usage

使用していないときは、ヒープ領域をすべてOSに戻したいのですが。プログラムが少なくとももう1時間は何もしないのに、私がそれを独り占めする理由はありません。

これは可能ですか?ありがとう。

51
jocull

あなたはおそらく_-XX:MaxHeapFreeRatio_をいじることができます-これは、GCがヒープを縮小する前に解放されるヒープの最大パーセンテージ(デフォルトは70)です。多分それを少し低く(40または50?)設定してからSystem.gc()を使用すると、望ましい動作が得られるまでに時間がかかる場合があります。

これを強制的に実行する方法はありませんが、JVMに強制的に実行させることはできますが、必要に応じてメモリを削除することはできません。そして、上記はヒープを縮小するかもしれませんが、そのメモリは必ずしもOSに直接戻されるとは限りません(ただし、JVMの最近の実装ではそうです)。

35
Michael Berry

ショートバージョン:はい、できます。

ロングバージョン:

Java/JVMがメモリを管理する方法

ほとんどのアプリケーションでは、JVMのデフォルトで問題ありません。 JVMは、アプリケーションが限られた期間だけ実行されることを期待しているようです。したがって、それ自体ではメモリを解放しないようです。

JVMがガベージコレクションを実行する方法とタイミングを決定できるようにするには、次のパラメーターを指定する必要があります。

  • _-Xms_最小ヒープサイズを指定します
  • _–Xmx_最大ヒープサイズを指定します

サーバーアプリケーションの場合:_-server_を追加します。

それだけでは十分ではありません。もっとコントロールしたい!

上記のパラメーターでは不十分な場合、ガベージコレクションに関するJVMの動作に影響を与えることができます。

最初に、System.gc()を使用して、ガベージコレクションが意味があると思われる場合にVMを通知できます。次に、JVMが使用するガベージコレクターを指定できます。

さまざまな種類のガベージコレクター:

  • シリアルGC

    コマンドラインパラメーター:_-XX:+UseSerialGC_

    アプリケーションを停止し、GCを実行します。

  • 並列GC

    コマンドラインパラメーター:_-XX:+UseParallelGC -XX:ParallelGCThreads=value_

    アプリケーションと並行してマイナーコレクションを実行します。 メジャーコレクションに必要な時間を短縮しますが、別のスレッドを使用します。

  • 並列圧縮GC

    コマンドラインパラメーター:_-XX:+UseParallelOldGC_

    アプリケーションと並行してメジャーコレクションを実行します。より多くのCPUリソースを使用し、メモリ使用量を減らします。

  • CMS GC

    コマンドラインパラメーター:_-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=value -XX:+UseCMSInitiatingOccupancyOnly_

    より小さなコレクションを実行し、Serial GCより頻繁に実行するため、アプリケーションの中断/停止を制限します。

  • G1

    コマンドラインパラメーター:_-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC_

    試験運用版(少なくともJava 1.6):アプリケーションが1秒以上停止しないようにしようとします。

最適化なしのPlay Framework Webアプリケーションのメモリ使用量: Play Framework WebApp without optimizations ご覧のとおり、ヒープ領域はかなり多く使用されており、使用された領域は定期的に解放されます。

この場合、パラメータのみを使用した最適化は効果がありませんでした。かなり多くのメモリを使用するいくつかのスケジュールされたタスクがありました。この場合、メモリを集中的に使用する操作の後に__CMS GC_をSystem.gc()と組み合わせて使用​​することにより、最高のパフォーマンスが得られました。その結果、WebAppのメモリ使用量は1.8 GBから約400〜500 MBに削減されました。

メモリがどのようにJVMによって解放され、実際にOSに返されるかを示すVisualVMの別のスクリーンショットを次に示します。

Memory is being freed by the JVM and returned to the OS 注:メモリを消費するスケジュールされたタスクは特定の時間にのみ起動されるため、コードでSystem.gc()ではなくVisualVMの[Perform GC]ボタンを使用してGCを実行しましたVisualVMでキャプチャするのは困難です。

参考文献

14
Peanut

JVMはそのようには機能しません。 OSに戻すことはできません。

これが4年前に作成されてから数人が述べたように、JVMに適切なGC設定を指定すると、メモリをOSに戻すことができます。

4
duffymo

Javaは秘密を厳守する:-Xincgcこれはパフォーマンスに影響を与えますが、常にそれほど影響を与えるわけではありません。時々、それはあなたがしていることに依存します。インクリメンタルガベージコレクターは、メモリをシステムに適切に戻します。

3
Mike

1つの可能性として、バックグラウンドJavaアプリケーションがタスクを実行するために毎時間外部jvmインスタンスを起動するようにします。これにより、元のjvmアプリケーションのみがタスク間で実行されます。

3
robert_x44

アプリが非アクティブな期間中に静止している場合、OSがそれらのページをスワップアウトして、物理メモリへのプレッシャーを軽減する可能性があります。

http://www.linuxvox.com/2009/10/what-is-the-linux-kernel-parameter-vm-swappiness/

3
Ron

Java 12は、G1GCを使用してこの機能をサポートしています。

JEP 346:G1から未使用のコミットされたメモリを即座に返します。

アイドル時にオペレーティングシステムにJavaヒープメモリを自動的に返すようにG1ガベージコレクターを拡張します。

https://openjdk.Java.net/jeps/346

Java 13はzgcを使用してこの機能をサポートしています

JEP 351:ZGC:Uncommit Unused Memory

ZGCは現在、メモリが長期間使用されていない場合でも、コミットを解除してメモリをオペレーティングシステムに返しません。この動作は、すべてのタイプのアプリケーションと環境、特にメモリフットプリントが問題となる環境に最適ではありません。例:リソースが使用によって支払われるコンテナ環境。

  • アプリケーションが長期間アイドル状態で、他の多くのアプリケーションとリソースを共有または競合している環境。

  • アプリケーションの実行中に、ヒープ領域の要件が大きく異なる場合があります。たとえば、起動時に必要なヒープは、安定した状態の実行中に後で必要になるヒープよりも大きい場合があります。

http://openjdk.Java.net/jeps/351

2
AlexB