Java 仮想マシン仕様によれば、プログラム カウンタに加えて、仮想マシン メモリの他のいくつかのランタイム領域も OutOfMemoryError 例外の影響を受けます。
この記事には主に次の OOM の紹介と例が含まれています。
よく話題になるOOM例外は実際にはエラーです 1. スタックオーバーフローエラー 1.1 バグを書く
JVM 仮想マシン スタックは深いです。メソッドを実行すると、スタック プッシュとスタック ポップが伴います。上記の方法からわかるように、メイン メソッドは実行後に再帰を継続し、最終的にスタックがバーストします。
1.2 原因分析
1.3 解決策
2. Javaヒープスペース Java ヒープはオブジェクト インスタンスを格納するために使用されます。オブジェクトを作成し続け、GC ルートからオブジェクトに到達可能なパスを確保して GC によるこれらのオブジェクトのクリアを回避する限り、オブジェクトの数が増加するにつれて、合計容量がヒープの最大容量制限に達し、メモリ オーバーフロー例外が発生します。 Java ヒープ メモリ OOM 例外は、実際のアプリケーションで最も一般的なメモリ オーバーフロー例外です。 2.1 バグを書く
コードは 2M の int 配列を割り当てようとします。起動パラメータ -Xmx12m が指定されている場合、割り当てられたメモリが不十分になります。これは、XXXL サイズのオブジェクトを S サイズの Java ヒープ スペースに詰め込むのと同様です。
2.2 原因分析
2.3 解決策 ほとんどの場合、-Xmx パラメータを使用して JVM ヒープ メモリ領域を増やすだけで済みます。それでも問題が解決しない場合は、次の状況を参照してさらに処理してください。
インタビュアー: メモリ リークとメモリ オーバーフローについてお話ししましょう。 知識ポイントをあげます。三つのことを続ければ、やがて偉大な神になれるだろう~~ メモリリークとメモリオーバーフロー メモリ不足とは、プログラムがメモリを要求したときに、使用するメモリ領域が不足し、結果としてメモリ不足になることを意味します。たとえば、Integer が要求されたが、Long でのみ格納できる数値が格納されている場合、メモリ オーバーフローが発生します。 メモリ リークとは、プログラムが要求したメモリ領域を解放できない状況を指します。単一のメモリ リークによって引き起こされる損害は無視できますが、メモリ リークが蓄積された場合の結果は非常に深刻です。メモリがどれだけあっても、遅かれ早かれ占有されてしまいます。 メモリ リークは最終的にメモリ不足につながります。 3. GCオーバーヘッド制限を超えた JVM にはガベージ コレクション メカニズム GC が組み込まれているため、Java 開発者はメモリを割り当てたり解放したりするために手動でコードを記述する必要がありません。ただし、Java プロセスが GC の実行に 98% 以上の時間を費やし、メモリの 2% 未満しか回復せず、このアクションが 5 回連続して繰り返されると、java.lang.OutOfMemoryError:GC オーバーヘッド制限超過エラー (一般にガベージ コレクション オーバーヘッドと呼ばれる) がスローされます。簡単に言えば、アプリケーションは基本的に利用可能なメモリをすべて使い果たしており、GC はそれを回収できません。 GC オーバーヘッド制限超過エラーがスローされない場合、GC によってクリーンアップされるわずかなメモリがすぐに再びいっぱいになり、GC が再度実行されることになり、CPU 使用率が 100% になり、GC の効果はほとんどなくなるという悪循環が続きます。 3.1 バグを書く このエラーが発生する例では、実際に無限ループを記述し、List または Map にデータを追加しているため、耐えられなくなるまで Full GC が発生します。簡単には見つからない例を次に示します。マップに 1000 個の要素を追加します。
出力結果から、1000 データという制限が機能せず、マップの容量が 1000 をはるかに超え、最終的に必要なエラーが発生したことがわかります。これは、Key クラスが hashCode() メソッドのみを書き換え、equals() メソッドを書き換えなかったためです。実際には、containsKey() メソッドを使用したときに問題が発生したため、GC がキーをクリーンアップできなくなるまで、HashMap にキーを追加し続けました。 インタビュアーがまた登場します。HashMapの原理と、なぜequalsとhashcodeを同時に実装する必要があるのかについて話しましょう。 このプログラムを実行する際の最終的なエラーも、JVM 構成に関連しています。設定されたヒープ メモリが小さすぎる場合は、Java ヒープ領域が直接報告されます。このエラーは、リソースが制限されているときにプログラムが停止する原因です。 3.2 解決策
4. ダイレクトバッファメモリ NIO を使用する場合、データの読み取りや書き込みに ByteBuffer を使用する必要があることがよくあります。これは、チャネルとバッファに基づいた I/O 方式です。ネイティブ関数ライブラリを使用してオフヒープ メモリを直接割り当て、Java ヒープに格納されている DirectByteBuffer オブジェクトをこのメモリへの参照として使用して操作を行うことができます。これにより、一部のシナリオで Java ヒープとネイティブの間でデータのコピーが回避され、パフォーマンスが向上します。 Java では、アプリケーションが Direct ByteBuffer を通じてオフヒープ メモリに直接アクセスできるようになります。多くの高性能プログラムは、メモリマップファイルと組み合わせた Direct ByteBuffer を通じて高速 IO を実現します。 4.1 バグを書く
ローカル メモリが継続的に割り当てられ、ヒープ メモリがほとんど使用されない場合、JVM は GC を実行する必要がなくなり、DirectByteBuffer オブジェクトはリサイクルされません。このとき、ヒープメモリは十分であるにもかかわらず、ローカルメモリが十分でない場合があり、OOM (ローカルダイレクトメモリオーバーフロー) が発生します。
最大直接メモリはデフォルトでコンピュータのメモリの 1/4 に設定されているため、これを小さく設定します。使用される直接メモリがこの値を超えると、OOM が発生します。
4.2 解決策
5. 新しいネイティブスレッドを作成できません 各 Java スレッドには一定量のメモリ領域が必要です。 JVM が基盤となるオペレーティング システムに新しいネイティブ スレッドの作成を要求すると、十分なリソースが割り当てられていない場合にこのタイプのエラーが報告されます。 5.1 バグを書く
5.2 原因分析
5.3 解決策 プログラムで作成されるスレッドの数を減らす方法を見つけ、アプリケーションが本当にそれほど多くのスレッドを作成する必要があるかどうかを分析します。 本当に多くのスレッドを作成する必要がある場合は、OS レベルで最大スレッド数を増やします。ulimia -a を実行して最大スレッド制限を表示し、ulimit -u xxx を使用して最大スレッド制限を調整します。 6. メタスペース JDK 1.8 より前では Permgen スペース エラーが表示されます。このエラーは、通常、ロードされているクラスが多すぎるか、サイズが大きすぎるために、永続世代がいっぱいになっていることを意味します。 1.8 で永続的な生成がキャンセルされたため、この例外は発生しなくなります。 Metaspace は、HotSpot のメソッド領域の実装です。メタスペースと永続世代の最大の違いは、メタスペースが仮想マシンのメモリ内になく、ローカル メモリを使用することです。ただし、ローカルメモリがいっぱいになる可能性があるため、例外が発生します。 6.1 バグを書く
SpringのGCLibでオブジェクトを動的に作成する
6.2 解決策 メソッド領域のオーバーフローも、一般的なメモリ オーバーフロー例外です。実行時に大量の動的クラスが頻繁に生成されるアプリケーション シナリオでは、これらのクラスのリサイクルに特別な注意を払う必要があります。前述の GCLib バイトコード拡張と動的言語に加えて、このタイプのシナリオには、多数の JSP または動的に生成された JSP ファイル (従来のソフトウェア業界では古くから存在していた可能性があります) を含むアプリケーション、OSGi ベースのアプリケーション (同じクラス ファイルが異なるローダーによってロードされた場合でも、異なるクラスと見なされます) なども一般的に含まれます。 メソッド領域は、一般的に JDK8 では生成が容易ではありません。 HotSpot は、予防的な役割を果たすことができるメタスペースを設定するためのいくつかのパラメータを提供します。
7. 要求された配列サイズが VM の制限を超えています 7.1バグを書く
これは比較的簡単です。非常に大きな配列を作成すると、OOM が発生します。これ以上は言いません。
JVM は配列の最大長を制限します。このエラーは、プログラムが最大長の制限を超える配列の作成を要求していることを示します。 配列にメモリを割り当てる前に、JVM は割り当てられるデータ構造がシステム内でアドレス指定可能かどうか (通常は Integer.MAX_VALUE-2) を確認します。 この種の問題は比較的まれです。通常、コードをチェックして、ビジネスでこのような大規模な配列を作成する必要があるかどうか、また、複数のブロックに分割してバッチで実行できるかどうかを確認する必要があります。 8. スワップ領域不足 Java アプリケーションを起動すると、限られた量のメモリが割り当てられます。この制限は、-Xmx およびその他の同様の起動パラメータによって指定されます。 JVM によって要求されたメモリの合計が使用可能な物理メモリより大きい場合、オペレーティング システムはメモリからハード ドライブへのスワップを開始します。 このエラーは、使用可能な仮想メモリがすべて使い果たされたことを示します。仮想メモリは、物理メモリとスワップ領域の 2 つの部分で構成されます。 こんなエラーは見たことないよ〜〜〜 9. プロセスを殺すか子供を犠牲にする オペレーティング システムはプロセスの概念に基づいて構築されます。これらのプロセスは複数のカーネル ジョブによって管理されます。そのうちの 1 つは「Out of memory Killer」と呼ばれ、使用可能なメモリが極端に少ない場合に特定のプロセスを「強制終了」します。 OOM Killer はすべてのプロセスにスコアを付け、スコアが低いプロセスを「強制終了」します。具体的なスコアリング ルールについては、「Surviving the Linux OOM Killer」を参照してください。 他の OOM エラーとは異なり、Killprocessorsacrifice 子エラーは JVM レベルではなく、オペレーティング システム レベルでトリガーされます。 9.1 原因分析 デフォルトでは、Linux カーネルは、プロセスによって要求されるメモリの合計量がシステムの使用可能なメモリよりも大きいことを許可します。この「ピークシフト」アプローチにより、システム リソースをより効率的に使用できます。 しかし、このアプローチは必然的に「過剰販売」という一定のリスクをもたらします。たとえば、一部のプロセスがシステム メモリを占有し続けると、他のプロセスに使用可能なメモリがなくなることがあります。このとき、システムは自動的に OOM Killer を起動し、スコアの低いプロセスを探し、それらを「強制終了」してメモリ リソースを解放します。 9.2 解決策
最後に偉大な神「ヤハイ」の写真を添付します 「Java 仮想マシン 3 版の詳細な理解」 https://plumbr.io/outofmemoryerror https://yq.aliyun.com/articles/711191 https://github.com/StabilityMan/StabilityGuide/blob/master/docs/diagnosis/jvm/Exception この記事はWeChatの公開アカウント「JavaKeeper」から転載したもので、著者はHaixingです。この記事を転載する場合はJavaKeeper公式アカウントまでご連絡ください。 オリジナルリンク: https://mp.weixin.qq.com/s/gIJvtd8rrZz6ttaoGLddLg |
<<: 7.10 カンファレンスまでのカウントダウン |エッジコンピューティングシナリオ向けにカスタマイズされた最初のモデル
>>: エッジコンピューティングの成功または失敗の鍵は何でしょうか?
v.ps(XTOMデータセンター傘下のクラウドサーバー)は現在、新製品シリーズであるシンガポールVP...
最近、7月のBaiduのアルゴリズム変更の話題に注目する人がおり、アルゴリズム変更によって生じたラン...
2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っていますあらゆるマ...
いつもの検索や「SEO」中に私が発見した簡単なルール: 1) Baidu の大規模な見直しにより、B...
毎日何百万ものマシンやオブジェクトがインターネットに接続される中、企業はエッジ コンピューティングを...
5月がまたやってきました。 2年前の今頃、百度プラットフォームが大規模なインターネット浄化キャンペー...
EC業界では、運営者としてPVやUVなどのデータを毎日監視し、レポートを毎日記入することが必須です。...
[51CTO.com からのオリジナル記事] 本日の re:Invent カンファレンスで、AWS ...
さらに読む: Qvodは調査に対して次のように回答した。「同社は通常通り営業しており、誰かが逮捕され...
パンデミックが人々に何かを教えてくれたとすれば、それは、これから何が起こるかは決して分からないという...
1.競合製品の分析方法を学ぶ競合分析は、あらゆる職種において最も重要なスキルの 1 つです。競合製品...
[[441163]]この記事から、raft をベースに分散 KV を構築していきます。 Raft は...
はじめに: 私の個人的な経験に基づいて、個人のマーケティングの可視性を構築する方法について書きます。...
月収10万元の起業の夢を実現するミニプログラム起業支援プランマーケティング用携帯電話の誕生以来、マー...
企業の発展と成長は、ユーザーの評判の浸透から切り離すことはできません。特に、成長段階にある新興企業は...