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 のパブリック アカウントにお問い合わせください。 |
>>: クラウドネイティブはクラウドコンピューティングの質的変化を促進し、デジタル変革への道を提供します
ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービスウェブサイトの構築を始め...
電子商取引市場調査の観点から百度有為の必然的な失敗を考察するBaidu Youa は、日常生活の消費...
私たちは皆、エッセイを書いたことがあります。もしトピックから外れたら、スコアがどれほど低くなるかはご...
5月28日、本日開催されたアリババクラウド北京サミットにおいて、常熟農村商業銀行とアリババクラウドは...
Suning.comは、6,600万ドルを投じて母子向け電子商取引大手のB2C Redbabyを買収...
【はじめに】昨日、小湘宇文はA5に「百度サーバー問題、ウェブサイトのスナップショットは実はオンライン...
長らく噂されていたBandwagonhost CN2 VPSは、今日ようやくニュースになりました。B...
速報: linode - 月額 10 ドル / メモリ 1g / SSD 24g / トラフィック ...
要点: JD Retail Cloud mPaaS における Flutter のホット リロードの原...
「WeChatマーケティング」は、Weiboに次ぐ強力なマーケティングプラットフォームであり、多くの...
JD.comは6月18日に大規模なプロモーションイベントを開催し、多くの顧客が参加しました。これは大...
2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っていますウェブサイ...
[[385285]]著者は、Raftアルゴリズムフレームワークraft-coreの独自のJavaバー...
調査会社ガートナーは、世界のパブリッククラウドサービス市場は2019年に予測された2,140億ドルか...
PTC (NASDAQ: PTC) は本日、PTC と ANSYS の最高の設計およびシミュレーショ...