Javaメモリオーバーフローシーンと解決方法

2936 ワード

Javaメモリオーバーフローとは、プログラムがメモリを申請する際に、使用するのに十分なスペースがなく、out of memoryが現れることである.スタックオーバーフロー(StackOverflowError)、スタックオーバーフロー(OutOfMemoryError:java heap space)、永続オーバーフロー(OutOfMemoryError:PermGen space)、OutOfMemoryError:unable to create native threadの4つのケースによく見られますが、以下にまとめます.
1、スタックオーバーフロー
       まずjavaスタック空間に何が格納されているかを明らかにします.JAvaスタック空間はスレッドプライベートであり、javaメソッドが実行するメモリモデルである.各メソッドの実行時にjavaスタック空間にスタックフレームが生成され、メソッドの変数テーブルが格納され、値などの情報が返され、メソッドの実行が終了するまでスタックフレームがスタックからスタックに入るプロセスです.
    したがって、スタックオーバーフローの原因は、通常、ループ呼び出し方法によってスタックフレームが増加し、スタックの深さが増加し、最終的にメモリが割り当てられないため、StackOverflowErrorが発生します.例えば、次のような場合です.
public class stack{

    public void test(){

        this.test();
    }
    public static void main(String[] args){
        for(; ; ;)
            new stack().test;
    }
}

スタックメモリオーバーフローは、通常、再帰的なデッドサイクルなどのプログラムエラーによって発生します.
2、スタックオーバーフロー
       JAvaスタックはスレッド共有領域であり、主にオブジェクトインスタンスを格納するために使用され、ほとんどのjavaオブジェクトがここでメモリを割り当てられ、JVMメモリ管理の最大の領域でもある.JAvaスタックメモリは若い世代と古い世代に分けられ、スタックメモリのオーバーフローは一般的に古い世代のオーバーフローである.プログラムが大量のオブジェクトインスタンスを作成し続け、GCによって回収されない場合、メモリオーバーフローが発生しやすい.オブジェクトが生成されると、主なプロシージャは次のようになります.
JVMはまず若い世代のEden区でメモリを割り当てます.
割り当てが成功すると、終了します.そうしないと、JVMはYoung GCをトリガーし、Eden領域の非アクティブなオブジェクトを解放しようとします.
リリース後に十分なメモリ容量がない場合は、Eden領域の一部のアクティブなオブジェクトをSuvivor領域に移行し、Suvivor領域が長期にわたって生存しているオブジェクトは古い年代に移行します.
古い年代の空間が足りない時、Full GCを触発して、古い世代に対して完全なごみの回収を行います;
回収後、Suvivorと古い世代がEdenからコピーされたオブジェクトを受信するのに十分なスペースがない場合、Eden領域は新しく生成されたオブジェクトにメモリを割り当てることができず、つまりオーバーフローします.
このことから,プログラムが多数のオブジェクトインスタンスを作成し続け,GCによって回収されない場合,メモリオーバーフローが発生しやすいことが分かる.次のようになります.
public class heap{
    public static void main(String[] args){
        ArrayList list = new ArrayList();
        while(true){
            list.add(new heap());
        }
    }
}

       スタックメモリのオーバーフローはメモリの漏洩を伴う可能性が高いので、まず漏洩する可能性のあるオブジェクトを調べ、ツールを通じてGC rootsリファレンスチェーンを検査し、漏洩したオブジェクトがどのようなリファレンス関係によってGCが彼らを回収できないことを発見しなければならない.メモリリークが存在しない場合、すなわちメモリ内のオブジェクトが生存し続ける必要がある場合は、仮想マシンのスタックパラメータを変更することでスタックメモリを大きくすることができます.
3、永続世代オーバーフロー
永続世代もjavaスタックメモリの一部であり、クラス名、アクセス修飾子など、Classに関する情報を格納するために主に使用されます.一般的な永続世代オーバーフローの原因は、大量のClassが動的にロードされ、GCによって回収されなかったためである.永続メモリパラメータを調整することでのみ解決できます.
4、ローカルスレッドを作成できません
オペレーティングシステムは、各プロセスのメモリに一定の制限があることを知っています.スタックメモリと非スタックメモリの割り当てが大きすぎると、残りのメモリが十分なスレッドスタックを作成するのに不足し、OutOfMemoryErrorが発生します.これにより、プロセスが消費する総メモリを大きくしたり、スタックメモリを小さくしたりして、問題を解決することができます.
 
まとめ:
  • スタックメモリオーバーフロー:プログラムが要求するスタックの深さが大きすぎるため.
  • スタックメモリオーバーフロー:メモリ漏洩かメモリ容量不足かを明らかにします.漏洩は対象がGC Rootにどのように引用されるかによって決まる.不足している場合は-Xms、-Xmxパラメータを大きくします.
  • 永続帯域メモリオーバーフロー:Classオブジェクトは解放されず、Classオブジェクトは情報を占有しすぎ、Classオブジェクトが多すぎる.
  • ローカルスレッドを作成できません:総容量が変わらず、スタックメモリ、非スタックメモリの設定が大きすぎると、スレッドに与えるメモリが不足します.

  • 参考ブログ:
    https://blog.csdn.net/u014131893/article/details/22474881
    https://blog.csdn.net/ni357103403/article/details/51940884/