Java ヒープメモリオーバーフローの概要分析

Java ヒープメモリオーバーフローの概要分析

Java ベースのエンタープライズ バックエンド アプリケーションを扱ったことがあるソフトウェア開発者なら、ユーザーまたはテスト エンジニアから次のような安っぽくて奇妙なエラー メッセージを受け取ったことがあるでしょう: java.lang.OutOfMemoryError: Java heap space。

この問題を理解するには、アルゴリズムの複雑さ、特に「空間」の複雑さというコンピュータ サイエンスの基礎に戻る必要があります。思い出していただければ、すべてのアプリケーションには最悪のケースの特性があります。具体的には、ストレージのサイズに関して、推奨よりも多くのストレージがアプリケーションに割り当てられることになり、これは予測不可能ですが深刻な問題です。これにより、ヒープ メモリが過剰に使用され、「メモリ不足」状態が発生しました。

[[226270]]

この特定の状況で最悪なのは、アプリケーションが修復できず、クラッシュしてしまうことです。最大メモリ (-Xmx オプション) を使用しても、アプリケーションを再起動しようとすると、長期的な解決策にはなりません。ヒープ使用量が増大または膨らむ原因を理解しなければ、メモリ使用量の安定性 (したがってアプリケーションの安定性) は保証されません。では、メモリに関連するプログラミングの問題を理解するためのより効果的な方法は何でしょうか?メモリ不足が発生した場合にこの質問に答える唯一の方法は、アプリケーションのメモリ ヒープと分散を理解することです。

この前提に基づいて、私たちは以下の側面に焦点を当てます。

  • メモリ オーバーフローが発生したときに Java プロセスのヒープ ダンプを取得します。
  • アプリケーションで発生しているメモリの問題の種類を理解します。
  • ヒープ アナライザーを使用すると、優れたオープン ソース プロジェクト Eclipse MAT を使用してメモリ リークを分析できます。

ヒープ分析の準備としてアプリケーションを構成する

メモリ リークのような非決定的かつ散発的な問題は、事後に分析するのが困難です。したがって、メモリ オーバーフローに対処する最善の方法は、JVM 仮想マシンに JVM 仮想マシンのメモリ状態のヒープ ファイルをダンプさせることです。

Sun HotSpot JVM には、メモリ オーバーフローがファイルに発生したときに JVM にヒープ状態をダンプするように指示するメソッドがあります。標準形式は .hprof です。したがって、この操作を実現するには、JVM 起動項目に XX:+HeapDumpOnOutOfMemoryError を追加します。メモリオーバーフローが発生するまでに長い時間がかかる可能性があるため、実稼働システムでもこのオプションを追加する必要があります。

ヒープ ダンプ .hprof ファイルを特定のファイル システムの場所に書き込む必要がある場合は、ディレクトリ パスを XX:HeapDumpPath に追加します。アプリケーションが指定されたディレクトリ パスへの書き込みアクセス権を常に持っていることを確認してください。

原因分析

101: メモリ不足エラーの性質を理解する

メモリ オーバーフロー エラーを評価して理解しようとする場合、最初に行うことはメモリ増加特性を観察することです。状況に応じて可能性を評価します。

スパイク型: このタイプのメモリ リークは、特定の種類の負荷がかかるとさらに激しくなります。 JVM が 20 人のユーザーにメモリを割り当てると、アプリケーションは正常に実行されます。ただし、100 人目のユーザーに達すると、メモリ ピークが発生し、メモリ オーバーフローが発生する可能性があります。この問題を解決するには 2 つの方法があります。

リーク: プログラミング上の問題により、メモリ使用量は時間の経過とともに徐々に増加します。

良好なガベージコレクションを備えた健全なグラフ

一定期間の健全性維持後の漏洩量の経時変化のグラフ

メモリ使用量の急増やメモリリークを引き起こすメモリグラフ

使用量の急増を引き起こすメモリの問題の性質を理解したので、分析から得られた推論に基づいて、次の方法を使用してメモリ不足エラーを回避できます。

メモリの問題の解決

メモリ リークの原因となったコードの修正: アプリケーションが、参照 (実行中のアプリケーションからのオブジェクト参照) をクリアせずに、一定期間にわたってオブジェクトを段階的に追加したため、プログラム エラーを修正する必要がありました。たとえば、このエラーは、ビジネス オブジェクトが段階的に追加されるハッシュ テーブルに挿入しているが、ビジネス ロジックとトランザクションが完了後にこれらのオブジェクトを削除していない場合に発生する可能性があります。

修正として最大メモリ値を増やします。実行中のメモリ特性とヒープについて理解した後、推奨される最大メモリ値ではアプリケーションの安定性を満たすことができないため、メモリ オーバーフローを再度回避するために、割り当てられた最大ヒープ メモリを増やす必要がある場合があります。したがって、ヒープ プロファイラーの評価に基づいて、Java -Xmx フラグをより高い値に更新してアプリケーションを実行する必要がある場合があります。

ヒープ分析

以下では、ヒープ分析ツールを使用してヒープダ​​ンプを分析する方法を詳しく分析します。この例では、Eclipse Foundation のオープン ソース ツール MAT を使用します。

MATを使用したヒープ分析

もっと深く掘り下げてみましょう。ヒープ メモリ オーバーフローの例を取得し、分析について考えるために、MAT のさまざまな表現とビューを調べるのに役立つ一連の手順を実行します。

1. メモリ オーバーフロー エラーが発生したときに生成された .hprof ヒープ ファイルを開きます。 MATは多くのインデックスファイルを作成するので、ダンプファイルを専用のフォルダにコピーしてください:ファイル -> 開く

2. ダンプ ファイルを開くと、メモリ リーク疑いレポートとコンポーネント レポートのオプションがあります。 「疑わしいリークレポートの実行」を選択します。

3. リーク疑いテーブルを開くと、プレビュー ウィンドウの円グラフに、オブジェクトごとに保持されているメモリの分布が表示されます。メモリ内の上位オブジェクト (最も多く保持されているメモリを持つオブジェクト - 蓄積されたメモリと参照されたオブジェクト) が表示されます。

4. 上記の円グラフは、メモリ参照 (独自のメモリと合計メモリ) が最も多いオブジェクトを集計して、3 つの容疑者を示しています。

それぞれのケースを一つずつ見ていき、それがメモリ不足エラーの根本原因であるかどうかを評価してみましょう。

疑わしい点1

「<システム クラス ローダー>」によってロードされた「java.lang.ref.Finalizer」の 454,570 インスタンスは、790,205,576 (47.96%) バイトを占有しました。

これは、割り当てられたアプリケーション メモリの約 50% を占める JVM ファイナライザー インスタンスが 454,570 個あることを示しています。

読者が Java Finalizer の機能を知っていると仮定すると、上記の情報から何がわかるでしょうか?

はじめに: http://stackoverflow.com/questions/2860121/why-do-finalizers-have-a-severe-performance-penalty

基本的に、開発者はインスタンスのリソースを解放するためにいくつかのカスタムファイナライザーを作成します。ファイナライザによって収集されたこれらのインスタンスは、別のキューを使用する JVM のガベージ コレクション アルゴリズムの範囲外です。実際、このパスはガベージ コレクション メカニズムのクリーンアップ パスよりも長くなります。では、これらのターミネータが実際に何を終了させるのかを考えてみましょう。

あるいは、sun.security.ssl.SSLSocketImpl の 20% を占めるポイント 2 が疑わしいのかもしれません。これらがファイナライザーによってファイナライズされるインスタンスであることを確認できますか?

疑わしい点2

ここで、MAT の上部にある [ツール] ボタンの下にある Dominator ビューを開きます。 MAT によって解析され、有効なヒープ ストレージを示す、リストされているすべてのクラス インスタンスが表示されます。

次に、Dominator ビューで、java.lang.Finalizer と sun.security.ssl.SSLSocketImpl の関係を理解し​​ようとします。 sun.security.ssl.SSLSocketImpl 列を右クリックし、GC ルート -> ソフト/弱い参照を除外を開きます。

ここで、MAT はメモリ グラフの描画を開始し、GC ルートへのパスとそれに対応するインスタンス参照を表示します。これは別のページに表示され、次の引用が表示されます。

上記の参照チェーンに示されているように、インスタンス SSLSocketImpl は java.lang.ref.Finalizer から取得され、SSLSocketImpl インスタンス全体は約 88k を占有します。また、ファイナライザ チェーンは、次のインスタンスを指すリンク リスト データ構造であることにも気付きます。

結論: この時点で、Java ファイナライザーが SSLSocketImpl オブジェクトを収集しようとしていることがはっきりとわかります。なぜこれほど多くの情報がまだ収集されていないのかを解明するために、コードを調べ始めました。

コードを確認する

コードをチェックして、ソケットが閉じられていることが原因かどうかを確認する必要があります。この場合、I/O に関連するすべてのストリームを適切に閉じる必要があることがわかります。ある時点で、JVM が原因であると疑いました。実は、Open JDK 6.0.XX の GC (ガベージ コレクター) のコードにバグがあります。

この記事が、Java アプリケーションのエラーがヒープ ストレージによって発生しているのか、内部の問題によって発生しているのかを分析するためのパターンを提供できたことを願っています。ヒーププロファイリングを楽​​しんでください!

さらに読む

浅いヒープと保持されたヒープ

浅いヒープは、1 つのオブジェクトによって消費されるメモリです。状況に応じて、オブジェクトには 32 ビットまたは 64 ビット (OS アーキテクチャによって異なります)、Integer の場合は 4 バイト、Long の場合は 8 バイトなどが必要になります。ヒープ ダンプの形式に応じて、メモリ サイズ (たとえば、8 に揃える) を調整して、VM の実際の消費量をより適切に調整できます。

X の保持セットは、X がガベージ コレクションされたときに削除されるオブジェクトのセットです。

X の保持ヒープは、X の保持セット内のすべてのオブジェクトの浅いヒープの合計、つまり X によって保持されるメモリです。

一般的に言えば、オブジェクトの浅いヒープはヒープ内のサイズです。同じオブジェクトの保持サイズは、オブジェクトがガベージ コレクションされたときのヒープ メモリの合計量です。

特定のクラスのすべてのオブジェクト、特定のクラス ローダーによってロードされたすべてのクラスのすべてのオブジェクト、または任意のオブジェクトなど、一部の主要なオブジェクト セットには、その主要なセットのすべてのオブジェクトがアクセス不能になった場合に解放されるオブジェクトのセットである保持セットがあります。

予約セットには、これらのオブジェクトと、これらのオブジェクトを通じてのみ取得できるその他のオブジェクトが含まれます。保持セットのサイズは、保持セットに含まれるすべてのオブジェクトのヒープ サイズです。

<<:  VMware の高可用性: サーバー仮想化におけるクラスター HA と FT

>>:  仮想化について語るパート 4 - コンピューティング仮想化における CPU 仮想化

推薦する

chicagovps-特別価格 KVM 利用可能/512M メモリ、年間 25 ドル/Win 互換

chicagovps 特別版 KVM がついに発売されました。512M メモリの KVM は年間 2...

SEO技術を利用して相手のウェブサイトに影響を与えるという恥知らずな行為について

いかなる技術にも二面性があります。善良な人々の手に渡れば、それは比類のない剣となり、無限の利益をもた...

海外マーケティングをワンストップで実現したいですか?海外メディア配信プラットフォームを選んでみませんか?

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています中国のモバ...

Perl は 2014 年 4 月の TIOBE プログラミング言語ランキングで過去最低を記録しました

TIOBE は 2014 年 4 月のプログラミング言語ランキングを発表しました。上位 3 位は C...

ロンドンオリンピックでの唐橋の成功の箱から得た6つのインスピレーション

時間、空間、人種、言語、文化を越えたスポーツイベント、ロンドンオリンピックを前に、すべての大手企業は...

新しいウェブサイトがBaiduに即日インデックスされた体験を共有する

今日、仕事で忙しかったのですが、突然友人から、私の新しいウェブサイトが Baidu にインデックスさ...

クラウドコンピューティングの8つの主な特徴

企業は最新のアプリケーション開発にクラウド テクノロジーを活用しています。クラウド コンピューティン...

NexusbytesのシンガポールVPSの簡単なレビュー

Nexusbytesは日本とシンガポールにデータセンターを展開しており、どちらもAMDプラットフォー...

「百度SEO事件」の本当の目的とは?

この記事を書いたとき、「百度SEO事件」は終結しましたが、それでも百度SEO事件の目的について考えず...

プラットフォームはHadoop分散ファイルシステムをサポート

Platform Computing (以下、Platform) は最近、Apache Corpor...

ユーザーエクスペリエンス分析:アリババ国際ステーションのホームページ再設計の概要

Alibaba.com は、世界最大かつ最も影響力のある B2B 電子商取引プラットフォームであり、...

Linux 仮想ファイルシステム (VFS) の関係を示す図

皆さんこんにちは。今日は Linux の仮想ファイルシステムについて説明します。仮想ファイルシステム...

SEOウェブサイトのページタイトルを最適化する際に注意すべきいくつかの重要なポイント

Jianzi SEO は、ウェブサイトのホームページやコラム ページであっても、ウェブサイトのロング...

edis-7 USD/月/1 GB RAM/100 GB ハードドライブ/4 TB データトラフィック

edisは、複数のデータセンターを所有する歴史あるVPSベンダーです。同社のVPSは、国内外のユーザ...