どんな種類のOutOfMemoryErrorがあり、Javaプロセスメモリはどの部分で構成されていますか

OutOfMemoryErrorをキャッチした場合、アプリケーションがガベージコレクターによってクリーニングできない多くのオブジェクトを作成し、-Xmxパラメーターを使用して選択したすべてのメモリを満たすことを意味するわけではありません。 少なくとも、このエラーを確認できる他の2つのケースを考え出すことができます。 実際、Javaプロセスのメモリは、アプリケーションがプログラムでオブジェクトを作成する-Xmx領域に限定されないということです。



画像







Javaプロセスが占有するメモリ領域は、いくつかの部分で構成されています。 OutOfMemoryErrorのタイプは、どれがスペースを使い果たしたかによって異なります。



1. java.lang.OutOfMemoryError:Javaヒープスペース



ヒープ上、つまり、アプリケーションでプログラムによって作成されたオブジェクトが配置されるメモリ領域に十分なスペースがありません。 サイズは-Xmsおよび-Xmxオプションで指定されます。 オブジェクトを作成しようとして、ヒープにスペースが残っていない場合、このエラーが発生します。 通常、問題は非常に多くのメモリリークにあり、インターネットはこのトピックに関する記事でいっぱいです。



2. java.lang.OutOfMemoryError:PermGenスペース



このエラーは、サイズが-XX:PermSizeおよび-XX:MaxPermSizeパラメーターで指定されている永続領域に十分なスペースがない場合に発生します。 そこにあるものとそこに発生するOutOfMemoryErrorに対処する方法については、すでにここで詳細に説明しています



3. java.lang.OutOfMemoryError:GCオーバーヘッド制限を超えました



このエラーは、1番目と2番目の領域のオーバーフロー中に発生する可能性があります。 これは、メモリがほとんど残っておらず、GCが常に動作しており、スペースを解放しようとしているという事実に関連しています。 このエラーは、-XX:-UseGCOverheadLimitパラメーターを使用して無効にできますが、もちろん無効にしないでください。ただし、メモリリークの問題を解決するか、より多くのボリュームを割り当てるか、GC設定を変更してください。



4. java.lang.OutOfMemoryError:新しいネイティブスレッドを作成できません



数年前、ストレステストを行い、Webアプリケーションで作業できる最大ユーザー数を把握しようとしていたときに、このエラーに初めて遭遇しました。 ユーザーがログインして標準アクションをエミュレートできる特別なツールを使用しました。 特定の数のクライアントで、OutOfMemoryErrorを取得し始めました。 メッセージのテキストを実際に読んでいないので、ユーザーセッションやその他の必要なオブジェクトを作成するのに十分なメモリがないと考えて、アプリケーションヒープのサイズを増やしました(-Xmx)。 その後、システムを同時に使用するユーザーの数が減っただけで驚いたことを想像してください。 これがどのように起こったかを詳しく見てみましょう。



実際には、プロセスが2 GBを超えないように割り当てるため、32ビットマシンのWindowsでの複製は非常に簡単です。



パラメーター-Xmx1024M -XX:MaxPermSize = 256M -Xss512Kで開始する多数の同時ユーザーを持つアプリケーションがあるとします。 プロセス全体で2Gを使用できる場合、別の768Mはまだ無料です。 スレッドのスタックが作成されるのは、この残りのメモリ内です。 したがって、おおよそ768 *(1024/512)= 1536(これらのパラメーターで1316を作成できました)スレッド(記事の冒頭の図を参照)しか作成できません。その後、OutOfMemoryErrorが発生します。 -Xmxを増やすと、作成できるスレッドの数はそれに応じて減少します。 より多くのスレッドを作成できるように-Xssを減らすオプションは、常に大きいとは限りません。システム内に非常に大きなスタックを必要とするスレッドがある可能性があるためです。 たとえば、初期化スレッドまたはいくつかのバックグラウンドタスク。 しかし、まだ解決策があります。 プログラムでスレッドを作成するときに、スタックサイズを指定できることがわかりましたThread(ThreadGroupグループ、Runnableターゲット、String name、long stackSize) 。 したがって、-Xssを非常に小さく設定し、上記のコンストラクターを使用して作成された個別のスレッドで大きなスタックを必要とするアクションを実行できます。



詳細については、ストリームスタックの内容と、このメモリの場所をここで読むことができます



もちろん、ほとんどのサーバーは現在64ビットアーキテクチャでスピンしているため、この問題はあなたには少し遠慮がちに思えるかもしれませんが、Javaプロセスメモリがどの部分で構成されているかを把握するのに役立つため、この例は非常に便利だと思います。



All Articles