OOMとは メモリ不足
- メモリ不足
- このエラーは、JVMにオブジェクト用のスペースを割り当てるのに十分なメモリがなく、ガベージコレクタにそれを再利用するためのスペースがない場合にスローされます。
なぜOOMなのですか?
つまり、なぜメモリがないのですか?
- 割り当てが少ない:仮想マシン自体が使用できるメモリが少なくなります(通常、起動時にVMパラメータによって指定されます)
- アプリケーションの使用量が多すぎるため、使い果たしても解放されず、無駄になります。このとき、メモリリークやメモリオーバーフローが発生します。
メモリリーク:アプリケーションが使用するメモリが解放されないため、仮想マシンが再び使用できないメモリが発生します。これは、申請者がメモリを使用しないため、JVMが他のメモリを割り当てることができないためです。
メモリオーバーフロー:要求されたメモリが、JVMが提供できるメモリサイズを超えています。
Javaヒープオーバーフロー
理由
- オブジェクトをJavaヒープに割り当てることができません
- アプリケーションは、GCでリサイクルできないオブジェクトを保持します
- アプリケーションがファイナライザーを使いすぎている
Javaヒープオーバーフローのトラブルシューティングのアイデア
1.次のような主要なエラーメッセージを見つける
java.lang.OutOfMemoryError: Java heap space
2.メモリイメージ分析ツール(Eclipsc Memory AnalyzerやJprofilerなど)を使用して、Dumpからのヒープストレージスナップショットを分析し、メモリリークかメモリオーバーフローかを分析します。
3.メモリリークの場合は、ツールを介してGC Rootへのリークされたオブジェクトの参照チェーンをさらにチェックして、アプリケーションのメモリリークを修正できます。
4.リークがない場合は、最初にコードに無限ループや再帰などがあるかどうかを確認し、次に-Xmxを使用してヒープサイズを増やすことを検討します。
スタックオーバーフロー
仮想マシンスタックとローカルメソッドスタックについては、Java仮想マシンスタック仕様に2つの例外が記述されています。
- スレッドによって要求されたスタックの深さが仮想マシンによって許可されたスタックの深さより大きい場合、StackOverflowError例外がスローされます。
- 仮想マシンを動的に拡張できる場合、拡張時に最大メモリを適用できないときにOutOfMemoryError例外がスローされます。
スタックオーバーフローの原因
- スレッドで、スタックフレームが大きすぎるか、仮想マシンのスタック容量が小さすぎる場合、メモリを割り当てることができないと、仮想マシンがStackOverflowError例外をスローします
- 常にスレッドを作成すると、例外またはメモリリークが発生します
ナレッジポイントの補足:
スタックはメソッドの呼び出しで作成され、メソッドが呼び出された後に破棄されます。ローカル変数やオペランドスタックなどのデータは、スタックフレームに格納されます。
Javaスタックは仮想マシンスタックとも呼ばれ、JVMスタックはスタックフレームの格納、プッシュ、ポップのみを行います。
- 各スレッドには、基本データ型のオブジェクトとカスタムオブジェクトへの参照のみがスタックに格納されるスタック領域が含まれます(オブジェクトではなく、オブジェクトはヒープ領域に格納されます)。
スタックオーバーフローのトラブルシューティングのアイデア
- 重要なエラーメッセージを見つけて、それがStackOverflowErrorかOutOfMemoryErrorかを判断します
- StackOverflowErrorの場合、コードが再帰呼び出しかどうかを確認します
- OutOfMemoryErrorの場合は、スレッドなどを作成するための無限ループがないか確認し、-Xssを使用して各スレッドスタックサイズの容量を減らします。
メソッド領域オーバーフロー
クラス名、アクセス修飾子、定数プール、フィールドの説明、メソッドの説明など、クラスの関連情報を格納するために使用されるメソッド領域(JDK8の後、永続的な世代とも呼ばれ、メタスペースは永続的な世代に置き換わります)実行時に多数のクラスが生成され、メソッド領域がいっぱいになります
メソッド領域オーバーフローの理由
- CGLibを使用して多数のプロキシクラスを生成し、メソッド領域をバーストさせます
- Java 7より前は、String.internが頻繁に誤って使用されていました
- 多数のjspおよび動的に生成されたjsp
- アプリケーションが再起動せずに長時間実行される
メソッド領域オーバーフローのトラブルシューティングのアイデア
- 永続生成スペースの設定が小さすぎるかどうかを確認してください
- 頻繁なエラーがないかコードを確認し、String.internメソッドを使用します
- jspに関連しているか確認してください。
- CGLibを使用して多数のプロキシクラスが生成されているかどうかを確認する
- Dafaを再起動し、JVMを再起動します
補足知識ポイント:
メソッド領域の定数プール:
- 定数プールは、リテラル定数プールとシンボリック参照定数プールに分かれています:
リテラル定数(値が格納されていることを示す):
1.テキスト文字列:1.テキスト文字列:
定義された文字列定数の値public String str = "Hello World" ;
"Hello World"は定数プールに格納されます
public String str1 = new String( "Hello Java"); "Hello Java"
の値は定数プールではなくヒープメモリに格納されます。
2.最終的な型の定数値:public final int age = 11、11の後に定数プールに格納されます
3.基本的なデータ型の値のバイト、short、int、float、double、long、char、boolean、すべて基本ではありませんデータ型の値はすべて定数プールに格納されます。byte、short、char、およびbooleanの4種類の値は定数プールに格納されません。
文字参照:参照の保存を示します。
1.クラスまたはインターフェースの完全修飾名:つまり、クラスまたはインターフェースの絶対パス名
2.フィールドの名前と記述子:クラス内の属性の名前と属性の説明。
3.メソッドの名前と記述子。