Javaの基本の要約(88)-メモリチューニング

元のリンク

メモリオーバーフローを解決したい場合、jvmで設定できるパラメータはどれですか?以下の説明のいくつかを見ると便利だと思います。

理想的には、JavaプログラムはJVMのデフォルト設定を使用して非常にうまく実行できるため、通常、JVMパラメーターを設定する必要はありません。ただし、パフォーマンスの問題がいくつかあるため(残念ながら、これらの問題は頻繁に発生します)、関連するJVMパラメーターに関する知識が私たちの作業の良いパートナーになります。この記事では、JVMメモリ管理に関するいくつかのパラメータを紹介します。これらのパラメータを理解して理解することは、開発者や運用および保守担当者にとって非常に役立ちます。

開発されたすべてのHotSpotメモリ管理およびガベージコレクションアルゴリズムは、同じヒープメモリ分割に基づいています。若い世代(若い世代)は新しく割り当てられた若いオブジェクトを格納し、古い世代(古い世代)は長寿命のオブジェクトを格納します。さらに、永続世代には、ロードされたオブジェクトのクラス定義やStringオブジェクトの内部キャッシュなど、JVMライフサイクル全体に付随する必要のあるオブジェクトが格納されます。次に、ヒープメモリが、若い、古い、永続的なという古典的な戦略に従って分割されていると仮定します。ただし、他のいくつかのヒープメモリ分割戦略も実行可能です。顕著な例は、新しいG1ガベージコレクターです。これは、若い世代と古い世代の区別を曖昧にします。さらに、現在の開発プロセスは、将来のHotSpot JVMバージョンでは、旧世代と永続世代の区別がないことを示しているようです。

-Xmsおよび-Xmx(または:-XX:InitialHeapSizeおよび-XX:MaxHeapSize)

-Xmsと-Xmxは間違いなく最も人気のあるJVMパラメータであり、JVMの初期および最大ヒープメモリサイズを指定できます。一般的に、これら2つのパラメーターの数値単位はバイトですが、同時に、「キロ」を表す「k」または「K」、「」を表す「m」または「M」などの省略表記の使用もサポートしています。メガ」、「g」「または「G」は「ギガ」の略です。たとえば、次のコマンドは、初期ヒープメモリが128M、最大ヒープメモリが2Gの「MyApp」という名前のJavaアプリケーションを起動します。

1 java -Xms128m -Xmx2g MyApp

実際の使用では、初期化されたヒープメモリのサイズは通常、ヒープメモリサイズの下限と見なされます。ただし、JVMは実行時にヒープメモリのサイズを動的に調整できるため、理論的には、ヒープメモリのサイズが初期ヒープメモリのサイズよりも小さいことがわかります。しかし、ヒープメモリの使用量が非常に少ない場合でも、このような状況に遭遇したことはありません。「-Xms」と「-Xmx」を同じサイズに設定することで固定サイズのヒープメモリを取得できるため、この動作は開発者とシステム管理者にとって便利です。-Xmsおよび-Xmxは、実際には-XX:InitialHeapSizeおよび-XX:MaxHeapSizeの略語です。これらの2つのパラメーターを直接使用することもできますが、同じ効果があります。

1 $ java -XX:InitialHeapSize=128m -XX:MaxHeapSize=2g MyApp

初期\最大ヒープメモリサイズのすべてのJVM出力は、フルネーム「InitialHeapSize」および「InitialHeapSize」を使用することに注意してください。したがって、-XX:+ PrintCommandLineFlagsパラメータを使用したりJMXを介してクエリを実行したりするなど、実行中のJVMのヒープメモリサイズをクエリする場合は、「Xms」および「Xmx」ではなく「InitialHeapSize」および「InitialHeapSize」フラグを探す必要があります。 。

-XX:+ HeapDumpOnOutOfMemoryErrorおよび-XX:HeapDumpPath

-Xmx(最大ヒープメモリ)に適切なサイズを設定できない場合、メモリ不足(OutOfMemoryError)のリスクに直面する可能性があります。これは、JVMを使用するときに直面する最も恐ろしい獣の1つです。このトピックに関する別のブログ投稿で述べたように、メモリリークの根本原因を注意深く特定する必要があります。一般的に言えば、ヒープメモリスナップショットの分析(ヒープダンプ)は適切なポジショニング方法です。メモリオーバーフローが発生したときにメモリスナップショットが生成されない場合、特にクラッシュした種類のJVMの場合、またはエラーが[数時間または数日もスムーズに稼働している本番システムの状況。

幸い、-XX:+ HeapDumpOnOutOfMemoryErrorを設定して、メモリオーバーフローが発生したときにJVMがヒープメモリスナップショットを自動的に生成できるようにすることができます。このパラメータを使用すると、メモリオーバーフローの例外に直面する必要があるときに多くの時間を節約できます。デフォルトでは、ヒープメモリスナップショットは、JVM起動ディレクトリのjava_pid <pid> .hprofという名前のファイルに保存されます(ここで、<pid>はJVMプロセスのプロセス番号です)。-XX:HeapDumpPath = <path>を設定して、デフォルトのヒープメモリスナップショット生成パスを変更することもできます。<path>は相対パスまたは絶対パスにすることができます。

これはすべて素晴らしいように聞こえますが、覚えておく必要のあることが1つあります。ヒープメモリスナップショットファイルは、特にメモリオーバーフローエラーが発生した場合、非常に大きくなる可能性があります。したがって、十分なディスク容量のある場所へのヒープメモリスナップショット生成パスを指定することをお勧めします。

-XX:OnOutOfMemoryError

メモリオーバーフローが発生した場合、管理者に通知するための電子メールの送信やクリーンアップ作業の実行など、いくつかの命令を実行することもできます。これは、一連のコマンドとそのパラメーターを受け入れることができるパラメーター-XX:OnOutOfMemoryErrorを使用して実行できます。ここでは詳細には触れませんが、例を示します。次の例では、メモリオーバーフローエラーが発生したときに、ヒープメモリスナップショットを/tmp/heapdump.hprofファイルに書き込み、JVM実行ディレクトリでスクリプトcleanup.shを実行します。

1 $ java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof -XX:OnOutOfMemoryError ="sh ~/cleanup.sh" MyApp

 -XX:PermSizeおよび-XX:MaxPermSize

永続的な生成は、JVMによってロードされたすべてのクラスのオブジェクト表現を含むヒープメモリ内の独立した領域です。アプリケーションを正常に実行するために、JVMは多くのクラスをロードします(それらは多数のサードパーティライブラリに依存しているため、より多くのライブラリに依存し、それらからクラスをロードする必要があります)。永続的な世代のサイズ。この目標を達成するために、-XX:PermSizeと-XX:MaxPermSizeを使用できます。このうち、-XX:MaxPermSizeは永続世代の最大値を設定するために使用され、-XX:PermSizeは永続世代の初期サイズを設定するために使用されます。簡単な例を次に示します。

1 $ java -XX:PermSize=128m -XX:MaxPermSize=256m MyApp

ここで設定した永続的な生成サイズは、パラメータ-XX:MaxHeapSizeで設定したヒープメモリサイズには含まれないことに注意してください。つまり、-XX:MaxPermSizeで設定された永続生成メモリは、パラメータ-XX:MaxHeapSizeで設定されたヒープメモリよりも多くのヒープメモリを必要とする場合があります。

-XX:InitialCodeCacheSizeおよび-XX:ReservedCodeCacheSize

JVMの興味深いが見過ごされがちなメモリ領域は「コードキャッシュ」です。これは、コンパイルされたメソッドによって生成されたネイティブコードを格納するために使用されます。コードキャッシングがパフォーマンスの問題を引き起こすことはめったにありませんが、一度発生するとその影響は壊滅的なものになる可能性があります。コードキャッシュがいっぱいになると、JVMは警告メッセージを出力し、インタープリター専用モードに切り替わります。JITコンパイラーは無効になり、バイトコードはマシンコードにコンパイルされなくなります。したがって、アプリケーションは引き続き実行されますが、誰かが問題に気付くまで、実行速度は1桁低下します。他のメモリ領域と同様に、コードキャッシュのサイズをカスタマイズできます。関連するパラメーターは-XX:InitialCodeCacheSizeおよび-XX:ReservedCodeCacheSizeであり、それらのパラメーターは上記のパラメーターと同じであり、すべてバイト値です。

-XX:+ UseCodeCacheFlushing

たとえば、ホットデプロイメントによって引き起こされたメモリリークが原因でコードキャッシュが増大し続ける場合、コードキャッシュサイズを増やしてもオーバーフローが遅れるだけです。この状況を回避するために、興味深い新しいパラメーターを試すことができます。コードキャッシュがいっぱいになったら、JVMにコンパイル済みコードを放棄させます。パラメータ-XX:+ UseCodeCacheFlushingを使用することで、コードキャッシュがいっぱいになったときに、少なくともJVMが解釈専用モードに切り替わるのを回避できます。ただし、メモリリークを見つけて修正するなど、コードキャッシュの問題の根本原因をできるだけ早く解決することをお勧めします。

おすすめ

転載: blog.csdn.net/lsx2017/article/details/114040368