JVM 関連の例外は、最前線の開発者にとって常に頭痛の種でした。なぜなら、ビジネス コードの場合、JVM の動作は基本的にブラック ボックスだからです。例外が発生した場合、直感的に問題を確認して見つけることは困難です。だからこそ、その内部ロジックを研究する必要があるのです。 この記事では、最近のオンライン JVM メモリ リークの例を使用して分析します。 パート1 オンラインサーバーが警報を発令ある日、同僚が助けを求めて私に来ました。あるシステムでは、何の警告もなく一連のアラームが発生していることが判明しました。旧世代のマシンのメモリ使用量がしきい値を超えました。 1.1 まずはパフォーマンスを見る 旧世代のメモリ使用量 7 月中旬までは、メモリ使用量は比較的正常であり、各 GC で古い世代のオブジェクトの大部分をリサイクルできたことがわかります。 月の中旬以降、旧世代のメモリが徐々に増加し、解放できなくなります。明らかに、これはオブジェクトが正常にリサイクルされていないことが原因であるはずです。 メモリリーク〜 1.2 何をすべきか 新しく立ち上げたプロジェクトでこのような問題が発生した場合、影響は比較的小さいため、コードを直接ロールバックして出血を止めることが最優先となります。 しかし、このプロジェクトは明らかに何日もオンラインになっており、その間にどれだけの要求があったかは不明です。また、最近のトラフィックの増加により問題が発生しているため、トラフィックが顧客に開放されたことを意味します。 ロールバックは不可能なので、急いで問題を特定し、オンラインで修正してください。 パート2 位置決めの問題一般的な手順:
ただし、ダンプされたファイルは 10G を超えて大きすぎるため、MAT は基本的に無力であり、手動で分析するために印刷することしかできません。 2.1 問題コードを見つける jmap 結果ビュー 幸いなことに、異常な物体は非常に明白です。 Point オブジェクトと GeoDispLocal オブジェクトのインスタンスは数百万あります。まず、これら 2 つのオブジェクトがコード内でどのように使用されるかを見てみましょう。
それらはすべて現在のキャッシュ CacheMap に格納されており (メモリ リークの一般的な原因は、静的コレクションによって保持され、リサイクルできないことです)、ダンプ ファイル内の CacheMap.Entry も非常に高くなります。 CacheMap が最優先の容疑者です。まず、このキャッシュ クラスがどのようなものかを見てみましょう。
内部的には LRU 機能を備えたマップに依存します。どのように実装されますか?
内部的には、LinkedHashMap を使用して実装された LRU キャッシュです。コメントによると、容量制限があり拡張性のないMAPを構築するのが目的だそうです(Baiduで調べたらネット上の実装と全く同じですね~)。では、実際の状況は本当に想像通りなのでしょうか? 2.2 LinkedHashMap によって実装された LRUMap は便利ですか? 容量と拡張に関する設定を見てみましょう。なぜ設計者は LRUMap が拡張しないと考えるのでしょうか?
実際の使用法に応じてインスタンス化してみましょう。
LRU 条件関数がオーバーライドされるため、サイズが 6000 を超えると LRU 置換が実行されます。したがって、理論上、サイズが 8110 に達することはありません。 同時読み取り/書き込み競合を解決するにはどうすればよいでしょうか?
同時実行時の読み取り/書き込み競合を解決するために、設計者はクエリおよび変更メソッドにロックを追加しました。パフォーマンスを考慮するために、読み取り/書き込みロックが使用されました。つまり、読み取りロックは get 中に追加され、書き込みロックは put/remove 中に追加されました。 全体的な設計により、LRUMap の固定容量と同時操作の問題がうまく解決されているように見えますが、真実は何でしょうか? 実際、この問題はずっと以前から分析されてきました[1]。これは、LinkedHashMap が読み取り/読み取り操作を実行するときに、LRU を維持するために要素を変更するため、つまり、要素をリンク リストの末尾に移動するためです。これは読み取り書き込み同時実行の問題につながりますが、この説明は漠然とした感じがするので、これに基づいて読み取り書き込み同時実行の問題をより詳しく説明することにしました。 2.3 LinkedHashMap メモリリーク解析 読み取り/書き込みロックが追加されても機能しないのはなぜですか? ここでは、読み取り/書き込みロックの概念と適用可能なシナリオを明確にする必要があります。読み取り/書き込みロックを使用すると、複数のスレッドが読み取りロックを共有できるため、書き込みよりも読み取りが多い状況に適しています。 (読み取り操作によってストレージ構造が変更されないことが前提です) したがって、get 操作で問題が発生します。 LinkedHashMap の get 操作は、LRU 機能を実装するために書き直されます。取得後、現在のノードはリンク リストの末尾に移動されます。 さあ、同志たち、これは明らかに書き込み操作なので、読み取りロックを追加することはまだ役に立ちますか? つまり、複数のスレッドが入り込み、変更が行われると、どのような影響があるのでしょうか?同時実行の問題は発生しないでしょうか? 次に、ノード移動コードを比較して、マルチスレッドでの同時実行の問題を詳細に分析します。 最後に到達したらノードを移動する 実際の逆アセンブリ分析は次のとおりです。マルチスレッドの状況でメモリ リークが発生する理由は次のとおりです。 タイムスライスでのマルチスレッドの取得実行 スレッド 1 が最初の 2 つのステートメントを実行した後、タイム スライスを放棄したことがわかります。スレッド 2 が p.after=null を実行すると、タイム スライスが再度放棄されました。このように、a は次の <2,B> ノードになるはずでしたが、マルチスレッドでは null になりました。最終的に、次の 2 つのノードがリンク リストから除外され、削除操作がそれらに到達できず、メモリ リークが発生しました。 認証コードはここには掲載しません。ご興味がございましたら、ぜひご自身でお試しください。 パート3の要約問題が特定されたので、このメモリ リークをどのように修正すればよいでしょうか? 読み取り/書き込みロックはミューテックス ロックに変更できます。あるいは、分散ストレージを直接使用した場合、速度はどのくらい遅くなるのでしょうか?これは便利で簡単で、マシンのメモリを節約するために LRUMap を自分で構築する必要がありません。 すべてのエッセイは面接のためだけのものではなく、あらゆるオンラインの問題のトラブルシューティングの基礎となります。八本足のエッセイの役割を誤解しないでください。 。 。 この記事はWeChatの公開アカウント「Coder's Technical Journey」から転載したものです。以下のQRコードからフォローできます。この記事を転載する場合は、Coder’s Technology Road のパブリック アカウントにお問い合わせください。 |
>>: クラウドネイティブはクラウドコンピューティングの質的変化を促進し、デジタル変革への道を提供します
記者は9月22日、雲斉大会組織委員会から、2021年杭州雲斉大会が10月19日から22日まで杭州雲斉...
2018年はオープンソースが人気で業界も非常に活況でした… [[257108]] 1. マイクロソフ...
zji は台湾のデータセンターに独立したサーバーを追加し、台湾の cn2 ネットワークに接続しました...
SEO が単純な個人のウェブサイトから求職活動、そして企業での業務へと移行すると、変更が必要な点が多...
私たちがマーケティング手法を見つけようと奮闘していたとき、スティーブ・ジョブズは最高レベルのマーケテ...
簡単に言えば、ソーシャルコメントプラグインとは、ウェブサイトに搭載して主にコメント機能を提供し、すべ...
外部リンクがウェブサイトの SEO パフォーマンスを向上させる方法はいくつかあります。1. ウェブサ...
[[351688]] 10年以上の開発を経て、クラウドコンピューティングは徐々に成熟してきました。こ...
m247 は 2001 年に設立され、ISO 9001:2008 品質管理システムと ISO2700...
タクシーを呼ぶためのよりクールな方法「タクシーが来ないまま、道端で長い間手を振っているより、別の方法...
【要点】 チャート操作の悪影響は誰もが知っていますが、利益を追求するために必死になって操作する人がま...
昨年の12月頃、友人から、私のウェブサイトを開くと広告がポップアップ表示されることに気付かされました...
IoT の 5 つのクラウドは、クラウドの役割を人々に理解してもらうために私が長い間開発してきたツー...
2018 年は、高利益率、急成長、クラウドの代替手段により、顧客が従来のオンプレミス ミドルウェア ...
[[440067]] Tair は、ダブル 11 ショッピング フェスティバル中のトラフィックのピー...