Java プログラムが JVM 上で実行されることは誰もが知っています。 JVM に何らかの障害が発生すると、サービスの安定性が必然的に影響を受けます。運が良ければ、サービスが不安定になり、一部のリクエストが遅延したり異常になったりする可能性があります。運が悪いと、JVM が直接クラッシュし、サービスが完全に中断されることになります。 これは良いことではありません。 JVM とともに、サービスだけでなく私たちの精神も崩壊するでしょう。 いわゆる JVM クラッシュは、一般的にメモリ オーバーフロー、つまり OutOfMemoryError と StackOverflowError を指します。もう 1 つの状況は、オフヒープ メモリの使用量が非常に大きい場合です。これにより、JVM が配置されているマシンのメモリが膨張し、マシンの再起動などの異常な状況が発生します。この状況をメモリ リークと呼びます。 では、どのような状況で JVM がクラッシュするのでしょうか?クラッシュにはどのような種類がありますか?諺にあるように、自分と敵を知ることによってのみ、百戦錬磨の勝者となることができるのです。クラッシュの原因を理解することによってのみ、JVM クラッシュの問題をより適切に解決できます。 まず、JVM メモリ モデル図を示します。 JVM は理解するのが非常に抽象的です。次の図は、JVM メモリ モデルを具体的に理解するのに役立ち、オーバーフローが発生する部分も図で確認できます。 JDK 8 では、永続世代は存在しなくなり、メタスペースに置き換えられました。 次に、Hotspot JDK 8 を背景として、JVM メモリ オーバーフローとメモリ リークのいくつかのケースを見ていきます。 まず、ヒープ領域のサイズを制限するために JVM 起動パラメータを設定します。ヒープ領域は、新世代用に 10M、メタスペース用に 10M を含む 20M に設定され、ガベージ コレクション アルゴリズムとして CMS アルゴリズムを使用するように指定します。以降のすべての例では、このパラメータ セットを使用します。
ヒープオーバーフロー ヒープ オーバーフローは、おそらく最も一般的なメモリ オーバーフローのシナリオです。 JVM に割り当てられたほとんどのオブジェクト インスタンスと配列はヒープ上に格納されます。さらに、ヒープメモリはガベージコレクターの主戦場でもあります。 Java プログラムが起動すると、ヒープ領域のサイズが指定されます。新しいオブジェクトと配列が作成されると、それらはヒープ上に割り当てられます。新しいオブジェクトがスペースを要求したときに、ヒープ メモリが不足している場合は、ガベージ コレクションが発生します。ほとんどの場合、これはマイナー GC と呼ばれる新しい世代で発生します。新しい世代が収集されてもまだ十分なスペースがない場合は、FullGC が発生します。 FullGC後も領域が不足している場合は、OOMエラー(ヒープオーバーフロー)が発生します。 このシナリオをシミュレートする
上記の方法は、 以下はプログラムを実行した後の結果です。ガベージ コレクション後も余分なスペースがないため、java.lang.OutOfMemoryError: Java ヒープ スペース例外が発生します。 画像-20201016211017630 ヒープ メモリ オーバーフローの根本的な原因は、使用中のオブジェクトのサイズがヒープ メモリ サイズを超えていることです。 ヒープメモリスペースの設定が小さすぎます。推定される実際のヒープ サイズに基づいて、ヒープ領域を適切に設定する必要があります。 プログラムの脆弱性により、一部の静的変数が増大し続けます。たとえば、キャッシュ データの初期化が不適切だと、キャッシュが際限なく大きくなり、最終的にはヒープ メモリのオーバーフローが発生します。この状況には、適切なテストを実施し、問題が発生した後に適切なログ分析を行う以外に、おそらく適切な解決策はありません。 スタックオーバーフロー 仮想マシン スタックは、ローカル変数テーブル、オペランド スタック、動的リンク、メソッド終了などの情報を格納するために使用されます。Java メソッドが呼び出されるたびに、仮想マシン スタック内にこのメソッドのスタック フレームが生成されます。 スタックには、仮想マシン スタックに加えて、ネイティブ メソッド スタックも含まれます。呼び出されたメソッドがネイティブ メソッド (C 言語で実装されたメソッドなど) の場合、ネイティブ メソッド スタックが使用されます。ただし、HotSpot 仮想マシンでは、仮想マシン スタックとローカル メソッド スタックが 1 つに結合されます。 スタックオーバーフローのシナリオをシミュレートする
上記のコードでは、stackOverflow() メソッドの呼び出しは、再帰終了のない無限再帰プロセスです。前述したように、メソッドが呼び出されるたびに、仮想マシン スタックにスタック フレームが生成されます。無限再帰は必然的にスタック フレームの無限生成を引き起こし、最終的にはスタック領域がいっぱいになり、オーバーフローが発生します。 画像-20201019122447325 上記は最も一般的な状況をシミュレートしたものです。この状況の原因はおそらくプログラムのバグによるものです。一般的に言えば、再帰には再帰的な終了が必要です。何らかの理由でプログラムが実行中に終了条件に到達できない場合、この例外が発生します。ループ本体もございます。ループ本体の反復回数が多すぎると、スタック オーバーフローが発生する可能性があります。 スレッドが多すぎるなど、可能性の低い他の理由もあるかもしれません。スレッドを作成するには、仮想マシン スタックにスペースを割り当てる必要があります。作成されるスレッドが多すぎると、OutOfMemoryError 例外が発生する可能性があります。ただし、一般的には手動でスレッドを作成するのではなく、スレッド プール方式を使用するため、このような状況が発生する可能性は低くなります。 メタスペース オーバーフローは、クラス情報、定数、静的変数、ジャストインタイム (JIT) コンパイル コード、および仮想マシンによってロードされたその他のデータを格納するために使用されます。 JDK 8 では、permanent 世代の代わりに metaSpace が使用されています。デフォルトでは、metaSpace のサイズは無制限、つまりサーバーの実際のメモリ サイズになります。ただし、一般的には、メタスペースのサイズを設定するのが最適です。 一般的に、動的に生成されるクラスが大量に生成されると、メタスペースのメモリ オーバーフローが発生する可能性があります。 メタスペースオーバーフローのシミュレーション
CGLIB を通じて多くの動的クラスを動的に作成すると、メタスペースに格納されるクラス情報が増え、メタスペース オーバーフローが発生します。 画像-20201019163227576 たとえば、Spring や MyBatis などの技術フレームワークを使用する場合、Bean インスタンス クラスが動的に作成されます。さらに、Spring AOP は動的プロキシ クラスも生成します。 オフヒープメモリオーバーフロー ほとんどの場合、メモリは JVM ヒープ メモリ内に割り当てられますが、まれにヒープ外部に直接メモリ領域を割り当てる必要がある場合もあります。オフヒープメモリを使用することによる利点はいくつかあります。
通常、オフヒープ メモリは、大量の頻繁な IO 操作が必要な場合に使用されます。たとえば、Netty と RocketMQ はオフヒープ メモリを使用してプロセスを高速化します。 したがって、システム メモリの使用量が非常に大きい場合は、スタックをチェックしても結果が出なかった場合、オフヒープ メモリの使用量をチェックして、オフヒープ メモリがオーバーフローしていないかどうかを確認できます。 要約する 事前に設定を行ってください JVM の問題自体は比較的抽象的で直感的に発見するのが難しいため、プロジェクトがオンラインになる前に、コード ロジックをテストするだけでなく、スタック サイズ、ガベージ コレクターの種類など、アプリケーションのサイズと特性に応じて JVM パラメータを合理的に構成し、適切なパラメータを選択することも必要です。 さらに、ガベージ コレクション ログを保持し、メモリ オーバーフローが発生したときにダンプ ファイルを保存する必要があります。 プロセスを監視する プログラムがオンラインのときは、Spring Admin などの軽量監視ツールを使用したり、大規模なプロジェクトの場合は Cat や SkyWallking などの分散リンク監視システムを使用したりして、JVM を適切に監視します。 現場での保護とその後の分析を提供する パラメータ構成と監視プラットフォームがどれほど合理的であっても、例外は必ず発生します。これは正常です。例外がない場合にのみ問題が生じます。例外が発生した後、シーンはタイムリーに保存される必要があります。マルチインスタンス アプリケーションの場合は、例外が発生したインスタンスを一時的にオフラインにして、問題をトラブルシューティングすることができます。単一インスタンスのサービスの場合は、最新のログとダンプが保存されていることを速やかに確認する必要があります。確認後、サービスを再起動するアクションを実行します。 この記事はWeChatの公開アカウント「古代の凧」から転載したものです。下のQRコードからフォローできます。この記事を転載する場合は、Ancient Kite の公開アカウントにご連絡ください。 |
<<: 専門家の予測:2021年にクラウドコンピューティング分野で出現するトレンド
>>: VMware が 3 年連続で Gartner Magic Quadrant の WAN エッジ インフラストラクチャのリーダーに選出
ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービス新しいメディアの急速な発...
百度が「価値の低いページはノー」と大胆に宣言して以来、業界に与えた衝撃は、間違いなく広島に投下された...
強力な機能と優れたスケーラビリティにより、Postgresql をベースにした分散アーキテクチャが数...
Tencent Lightweight Application Server (Lighthouse...
ウェブサイトのスナップショットは、ウェブマスターにとって常に関心事です。友好的なリンクの交換やウェブ...
v.ps は、デフォルトの帯域幅が 1Gbps で、中国本土向けに特別に最適化され、3 つのネットワ...
日本は中国本土に最も近い隣国の一つであり、ネットワークが発達しています。中国、ヨーロッパ、アメリカへ...
少し前に、ウエディングドレスの海外取引を行っている電子商取引会社が、その成功体験をシェアしているとい...
2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています著者: ジ...
AppleのiPhoneは第8世代まで進化しました。外観も機能もますます完璧になり、より使いやすくな...
記者らは昨日、国務院の関連指示に基づき、インターネット金融の発展以来最大規模の政府調査が8月1日に開...
クラウド コンピューティングについて関係者と話していると、最後に IaaS、PaaS、SaaS など...
ウェブサイトの重みを改善することは、SEO を行うすべての人が毎日行っていることです。しかし、ウェブ...
研修記者の季家鵬が北京からレポートSina Weiboでお金を稼ぐのはもう簡単ではありません。記者の...
nodeserv は 2009 年に設立され、比較的運営歴が短いです。openvz に基づく VPS...