JAva仮想マシン学習(三)メモリオーバーフロー異常
2418 ワード
public class Main {
private static int count=0;
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
deap();
}catch(Exception ex){
ex.printStackTrace();
}
}
private static void deap(){
count++;
System.out.println(count);
deap();
}
}
-Xssを1 Mと10 Mに設定すると、出力されるカウント変数は10倍ほど悪くなりますが、仮想スタック実行時はjavaメソッド実行時メモリモデルであり、無限の再帰時には実行時の操作数、局所変量メソッド出力などの情報を格納するためにスタックフレームを仮想スタックに押し込むことが理解されます.このメモリがいっぱいになると、スタックがオーバーフローします.
オペレーティングシステムでは、各プロセスのメモリ上限が制限されています.各プロセスのメモリサイズの上限が1 GBであることを規定すると、仮想マシンでは、メソッド領域のメモリとスタックメモリは、仮想マシンパラメータ設定(xmxとmaxPerSize)、仮想マシンプロセスのメモリからスタックメモリとメソッド領域の合計メモリを減算することができます.カウンタと仮想マシン自体が実行するために消費されるメモリ(この2つの部分が占めるメモリが小さい)を無視すると、基本的に残りのメモリは仮想マシンスタックとローカルメソッドスタックで分割されます.各スレッドに割り当てられた仮想マシンスタックのメモリが大きいほど、作成できるスレッドの数は少なくなります.
3.メソッド領域と実行時定数プールのオーバーフロー:
メソッド領域メモリサイズの設定は、仮想マシンパラメータ-XX:PermSizeおよび-X: MaxPermSizeで設定できます.java 1.6環境では、次のコードでメソッド領域定数プールメモリオーバーフローを実現できます.
public static void main(String[] args) {
// TODO Auto-generated method stub
int i=0;
ArrayList<String> list=new ArrayList<String>();
while(true){
list.add(String.valueOf(i++).intern());
}
}
ここでString.intern()メソッドの役割は、文字列定数プールにこのStringオブジェクトに等しい文字列が存在する場合、参照を返します.そうしないと、この文字列が定数プールに格納されます.java 1.6の定数プールは永続メモリに割り当てられ、gcはほとんど回収されません.したがって、定数プールメモリはオーバーフローします.(1.7仮想マシンで文字列定数プールが永続世代から削除されました)メソッド領域を埋め込むメモリはgclibを使用して大量のクラスを作成することができます.なぜなら、メソッド領域はクラスクラスクラスクラスクラスクラスの関連情報を格納するために使用されるためです.例えば、クラス名、アクセス修飾子、定数プールなど、Spring、OSGIなどの主流フレームワークではこのような問題が発生します.このようなフレームワークは大量のクラスをロードする必要がありますが、1つのクラスの判定条件を回収するのは厳しいので、メソッド領域でメモリの割り当てが小さいとOutOfMemoryError:PerGen space異常、すなわちメソッド領域オーバーフローを報告します.
4.ネイティブメモリオーバーフロー:
DirectMemoryの容量は、仮想マシンのパラメータ-XX:MaxDirectMemorySizeを設定ことで設定することができる、実験方法:直接メモリ上限を設定した後、unsafe類のallocateMemory()メソッドでメモリを申請し続け、上限に達するとOutOfMemory異常と報告する.
リファレンス接続:
http://lavasoft.blog.51cto.com/62575/25492/