JVM は、ヒープと非ヒープの 2 種類のメモリを管理します。ヒープは開発者が使用するもので、前述したように、JVM の起動時に作成されます。非ヒープは JVM 自体がクラス情報を保存するために予約されています。ヒープとは異なり、GC は実行時にスペースを解放しません。
1. メモリオーバーフロー型
1. java.lang.OutOfMemoryError: PermGen スペース
JVM は、ヒープと非ヒープの 2 種類のメモリを管理します。ヒープは開発者が使用するもので、前述したように、JVM の起動時に作成されます。非ヒープは JVM 自体がクラス情報を保存するために予約されています。ヒープとは異なり、GC は実行時にスペースを解放しません。 Web アプリが大量のサードパーティ jar を使用している場合、またはアプリケーションのクラス ファイルが多すぎて MaxPermSize 設定がたまたま小さい場合、制限を超えるとメモリが占有されすぎてオーバーフローが発生するか、Tomcat がホットデプロイメント中にフロントをクリーンアップしないと、ロードされた環境はコンテキストを新しくデプロイされたものに変更するだけであり、スタックしないコンテンツがますます増えます。
PermGen スペースの完全な名前は永続生成スペースであり、このメモリは主に JVM がクラスとメタ情報を保存するときに PermGen スペースに配置されるために使用されます。 (インスタンス) ヒープ領域が異なり、メイン プログラムの実行中に GC (ガベージ コレクション) が PermGen 領域をクリーンアップしないため、アプリケーションに多くの CLASS がある場合は、PermGen を使用します。登場する可能性が高いです。スペース エラー。このエラーは、Web サーバーが JSP をプリコンパイルするときによく発生します。 WEB APP が多数のサードパーティ jar を使用しており、そのサイズが jvm のデフォルト サイズ (4M) を超える場合、このエラー メッセージが生成されます。
最良の構成例: (私自身で検証したところ、この構成を使用して以来、Tomcat は一度も停止しませんでした)
set JAVA_OPTS=-Xms800m -Xmx800m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m
Linux では、tomcathome/conf/catalina.sh に赤で示されているコード行を追加します。tomcat jvm のメモリを増やすことができるため、メモリ オーバーフローが発生する可能性が低くなります。
# ----- 要求されたコマンドを実行 -------------------------------------- -
JAVA_OPTS="-server -Xms512m -Xmx2048m -XX:PermSize=128m -XX:MaxNewSize=256m -XX:MaxPermSize=256m"
# Bugzilla 37848: TTY がある場合にのみこれを出力します
2. java.lang.OutOfMemoryError: Java ヒープ領域
最初の状況は補足であり、主な問題はこの状況で発生します。デフォルトのスペース (-Xms) は物理メモリの 1/64 で、最大スペース (-Xmx) は物理メモリの 1/4 です。メモリの残りが 40% 未満の場合、JVM はヒープを Xmx で設定された値まで増やします。メモリの残りが 70% を超えると、JVM はヒープを Xms で設定された値まで減らします。したがって、各 GC 後に仮想マシン ヒープのサイズが調整されることを避けるために、サーバーの Xmx 設定と Xms 設定は通常同じに設定する必要があります。物理メモリが無限であると仮定すると、最大 JVM メモリはオペレーティング システムによって異なります。通常、32 ビット マシンは 1.5g から 3g の間ですが、64 ビット マシンには制限がありません。
注: Xms が Xmx 値を超える場合、または最大ヒープ値と最大非ヒープ値の合計が物理メモリまたはオペレーティング システムの最大制限を超える場合、サーバーは起動しません。
ガベージコレクション GC の役割
JVM が GC を呼び出す頻度は依然として非常に高く、ガベージ コレクションは主に次の 2 つの状況で実行されます。
アプリケーション スレッドがアイドル状態の場合、もう 1 つは Java メモリ ヒープが不足している場合であり、継続的なリサイクルによってメモリ ヒープ不足の問題が解決できない場合は、メモリ不足エラーが報告されます。この例外はシステムの動作環境に依存するため、いつ発生するかを予測することはできません。
GC メカニズムによれば、プログラムの実行によりシステムの動作環境が変化し、GC がトリガーされる可能性が高くなります。
これらの問題を回避するには、プログラムの設計と作成において、ガベージ オブジェクトによるメモリ占有と GC のオーバーヘッドを回避する必要があります。 System.GC() を明示的に呼び出すと、JVM がメモリ内のガベージ オブジェクトをリサイクルする必要があることが示唆されるだけですが、すぐにリサイクルする必要はありません。
1 つは、メモリ リソース不足の問題を解決できず、GC の消費量も増加することです。
2. JVMメモリ領域の構成<BR>Javaにおけるヒープとスタックについて簡単に説明します。
Java では、メモリを 2 つのタイプに分類します。1 つはスタック メモリ、もう 1 つはヒープ メモリです。
1. 関数内で定義された基本型変数とオブジェクト参照変数は関数のスタックメモリに確保されます。
2. ヒープ メモリは、new によって作成されたオブジェクトと配列を格納するために使用されます。関数 (コード ブロック) で変数が定義されると、Java は変数のスコープを超えると、その変数にメモリ領域を割り当てます。変数に割り当てられたメモリ領域を削除します。ヒープに割り当てられたメモリは、Java 仮想マシンの自動ガベージ コレクタによって管理されます。ヒープの利点は、メモリ サイズと有効期間を動的に割り当てることができることです。メモリ内にあるため、実行時に動的に割り当てられるため、事前にコンパイラに通知する必要はありません。欠点は、実行時にメモリを動的に割り当てる必要があり、アクセス速度が遅いことです。
スタックの利点は、アクセス速度がヒープよりも速いことです。欠点は、スタックに格納されるデータのサイズと有効期間が決定的で柔軟性に欠けることです。
Java ヒープは、New、Old、Permanent の 3 つの領域に分かれています。
GC には 2 つのスレッドがあります。
新しく作成されたオブジェクトは New 領域に割り当てられ、その領域がいっぱいになると、GC 補助スレッドによって Old 領域に移動され、Old 領域もいっぱいになると、GC メイン スレッドがトリガーされて、その領域内のすべてのオブジェクトが走査されます。ヒープメモリ。 Old 領域のサイズは、Xmx から -Xmn を引いた値に等しくなります。
Java スタック ストレージのスタック調整: パラメーターは +UseDefaultStackSize -Xss256K です。これは、各スレッドが 256k のスタック領域を適用できることを意味します。各スレッドは独自のスタックを持ちます。
3. JVM で仮想メモリを設定する方法<BR>ヒント: JVM では、時間の 98% が GC に使用され、使用可能なヒープ サイズが 2% 未満の場合、この例外メッセージがスローされます。
ヒント: 最大ヒープ サイズは、使用可能な物理メモリの 80% を超えてはなりません。通常、-Xms オプションと -Xmx オプションは同じ値に設定し、-Xmn は -Xmx 値の 1/4 に設定する必要があります。
ヒント: JVM によって割り当てられる初期メモリは -Xms で指定され、デフォルトは物理メモリの 1/64 です。JVM によって割り当てられる最大メモリは -Xmx で指定され、デフォルトは物理メモリの 1/4 です。メモリ。
デフォルトでは、空きヒープ メモリが 40% 未満の場合、JVM は -Xmx の最大制限までヒープを増やします。空きヒープ メモリが 70% を超える場合、JVM は最小制限の -Xmx までヒープを減らします。 -Xms。したがって、サーバーは通常、各 GC 後にヒープ サイズが調整されることを避けるために、-Xms と -Xmx が等しくなるように設定します。
ヒント: 物理メモリが無限であると仮定すると、JVM メモリの最大値はオペレーティング システムと大きな関係があります。
簡単に言うと、32 ビット プロセッサには 4GB の制御可能なメモリ空間がありますが、特定のオペレーティング システムによって制限が課せられます。
この制限は通常 2GB ~ 3GB (一般的に、Windows システムでは 1.5G ~ 2G、Linux システムでは 2G ~ 3G) で、64 ビットを超えるプロセッサには制限はありません。
注: Xms が Xmx 値を超える場合、または最大ヒープ値と最大非ヒープ値の合計が物理メモリまたはオペレーティング システムの最大制限を超える場合、サーバーは起動しません。
ヒント: NewSize と MaxNewSize を等しく設定し、「新しい」のサイズを「古い」の半分より大きくしないでください。その理由は、古い領域が十分に大きくないと「メイン」GC が頻繁にトリガーされるためです。パフォーマンスが大幅に低下します。
JVM は -XX:PermSize を使用して非ヒープ メモリの初期値を設定します。デフォルトは物理メモリの 1/64 です。
ヒープ以外の最大メモリ サイズは XX:MaxPermSize によって設定されます。デフォルトは物理メモリの 1/4 です。
解決策: ヒープ サイズを手動で設定する
TOMCAT_HOME/bin/catalina.bat を変更する
「echo "Using CATALINA_BASE: $CATALINA_BASE"」の上に次の行を追加します。
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:MaxNewSize=256m"
4. パフォーマンス チェック ツールを使用してメモリ リークを特定します。
JProfiler ツールは、主にシステム (Java 開発に限定) のパフォーマンスをチェックおよび追跡するために使用されます。 JProfiler は、システムのメモリ使用量、ガベージ コレクション、スレッドの実行ステータスなどを随時監視することで、JVM の動作とパフォーマンスを監視できます。
1. アプリケーションサーバーのメモリが長時間不当に占有される メモリが高いレベルで占有されることが多く、低いレベルに回復することが困難です。