Javaヒープは、オブジェクトインスタンスを保存するために使用されます。したがって、オブジェクトを継続的に作成し、GCルートと作成されたオブジェクトの間にアクセス可能なパスがあることを確認して、オブジェクトが収集されることを避けるために、オブジェクトが作成されすぎると、Heapメモリが不十分になり、OutMemoryErrorの例外が生じます。
/** * @author xiongyongshun * vm args:java -xms10m -xmx10m -xx:+heapdumponoutofmemoryerror */public class outofmemoryerrortest {public static void main(string [] args){list <integer> list = new arraylist <> int i = 0; while(true){list.add(i ++); }}}上記は、OutFmeMoryErrorの例外を提起するコードです。リスト内のオブジェクトを絶えず作成および保存することによって、オブジェクトが収集されることを防ぐことができます。したがって、オブジェクトが多すぎると、ヒープメモリがオーバーフローします。
java -xms10m -xmx10m -xx:+heapdumponoutofmemoryerrorを介して、ヒープメモリを10メガバイトに設定し、パラメーター-xx:+heapdumponofmemoryErrorを使用して、JVMを使用して、outofmemoreror例外の場合にjvmを印刷します。
上記のコードをコンパイルして実行した後、次の出力は次のとおりです。
>>> java -xms10m -xmx10m -xx:+heapdumponoutofmemoryerror com.outofmemoryerrortest 16-10-02 23:35java.lang.outofmemoryerror:java heap spacedump to Java_pid1810.hap 0.125秒]スレッドの例外「メイン」java.lang.outofmemoryerror:java.util.arrays.copyof(arrays.java:3210)のjava.util.arrays.copyof(arrays.java:3181) java.util.arraylist.ensureexplicitcapacity(arraylist.java:235)at java.util.arraylist.ensurecapacityinternal(arraylist.java:227)at java.util.arraylist.add(arraylist.java:458)at java.util.arraylist.add( com.test.outofmemoryerrortest.main(outofmemoryerrortest.java:15)
Java StackoverFlowerror
JVMのランタイムデータ領域に仮想マシンスタックと呼ばれるメモリ領域があることを知っています。この領域の機能は次のとおりです。各メソッドは、実行時にスタックフレームを作成します。これは、ローカル変数テーブル、オペランドスタック、メソッドエキシットなどの情報を保存するために使用されます。
したがって、無限に再帰的な再帰コールを作成できます。再帰的な深さが大きすぎると、スタックスペースが使い果たされ、StackoverFlowerrorの例外が発生します。
これが特定のコードです:
/** * @author xiongyongshun * vm args:java -xss64k */public class outofmemoryerrortest {public static void main(string [] args){stackoutofmemoryerror(1); } public static void stackoutofmemoryerror(int dept){depth ++; stackoutofmemoryerror(深さ); }}上記のコードをコンパイルして実行すると、次の例外情報が出力されます。
com.test.outofmemoryerrort.stackoutofmemoryerror(outofmemoryerrort.java:27)のスレッド「main」java.lang.stackoverflowerrorの例外
メソッド領域のメモリオーバーフロー
JDK8は永久生成を削除し、JDK8でMetaspaceに置き換えたため、次の2つの例のいずれもJava.lang.OutofMemoryError:Permgen Space Exceptionを引き起こすことはありません。
ランタイム中に一定のプールがオーバーフローします
Java 1.6およびHotspot JVMの以前のバージョンでは、永続的な生成の概念があります。つまり、GCの生成収集メカニズムがメソッド領域に拡張されます。メソッド領域では、メモリの一部を使用して、一定のプールを保存します。したがって、コードに定数が多すぎると、一定のプールのメモリが使い果たされ、メモリオーバーフローが発生します。では、一定のプールに多数の定数を追加するにはどうすればよいですか?現時点では、string.intern()メソッドに依存する必要があります。 string.intern()メソッドの関数は次のとおりです。この文字列の値が定数プールに既に存在する場合、このメソッドは定数プールの対応する文字列への参照を返します。それ以外の場合は、この文字列に含まれる値を定数プールに追加し、この文字列オブジェクトへの参照を返します。 JDK 1.6および以前のバージョンでは、一定のプールが恒久的な世代に割り当てられています。したがって、パラメーター「-xx:permsize」および「-xx:maxpermsize」を設定することにより、一定のプールのサイズを間接的に制限できます。
上記のstring.intern()メソッドのメモリ分布と定数プールは、JDK 1.6および以前のバージョンのみであることに注意してください。 JDK 1.7以上では、永久生成の概念が削除されるため、メモリレイアウトはわずかに異なります。
以下は、一定のプールのメモリオーバーフローを実装するコードの例です。
/** * @author xiongyongshun * vm args:-xx:permsize = 10m -xx:maxpermsize = 10m */public class runtimeconstantpooloomtest {public static void main(string [] args){list <string> list = new arraylist <string>(); int i = 0; while(true){list.add(string.valueof(i ++)。intern()); }}}この例では、string.intern()メソッドを正確に使用して、一定のプールに多数の文字列定数を追加することがわかります。
JDK1.6を介して上記のコードをコンパイルして実行すると、次の出力が次のとおりです。
スレッド「Main」Java.Lang.OutofMemoryError:java.lang.string.intern(native method)のpermgenスペース:runtimeconstantpooloomtest.main(runtimeconstantpooloomtest.java:16)
上記のコードがコンパイルされてJDK1.8を介して実行されている場合、次の警告があり、例外が生成されないことに注意してください。
>>> java -xx:permsize = 10m -xx:maxpermsize = 10m com.test.runtimeconstantpooloomtest 16-10-03 0:23java hotspot(tm)64ビットサーバーVM警告:オプションの無視Permsize = 10m;サポートは8.0 Java Hotspot(TM)64ビットサーバーVM警告で削除されました。サポートは8.0で削除されました
メソッド領域のメモリオーバーフロー
メソッド領域の機能は、クラス名、クラスアクセス修飾子、フィールドの説明、メソッドの説明など、クラスの関連情報を保存することです。したがって、メソッド領域が小さすぎてクラスがロードされている場合、メソッド領域のメモリオーバーフロー。
// vm args:-xx:permsize = 10m -xx:maxpermsize = 10mpublic class methodareaoomtest {public static void main(string [] args){while(true){enchancer enthancer = new Enhancer(); Enhancer.setsuperclass(methodareaoomtest.class); Enhancer.SetUseCache(false); Enhancer.setCallback(new MethodEnterceptor(){public object intercept(Object o、Method Method、Objects、MethodProxy MethodProxy)Throws {return MethodProxy.Invokesuper(o、objects);}}); Enhancer.create(); }}}上記のコードでは、CGLIBを使用して、多数のクラスを動的に生成します。 JDK6では、上記のコードを実行すると、OutOfMemoryErrorが生成されます。
/system/library/frameworks/javavm.framework/versions/1.6/home/bin/java -jar -xx:permsize = 10m -xx:maxpermsize = 10m Target/test -1.0 -snapshot.jar
出力の結果は次のとおりです。
原因:java.lang.outofmemoryerror:java.lang.classloader.defineclass1のpermgenスペースjava.lang.classloader.defineclasscond(classloader.java:637)のjava.lang.lang.classoloader.defineclass(classloader.defineclass(classloader.java:637)
Metaspaceメモリオーバーフロー
メソッド領域のメモリオーバーフローメモリオーバーフローセクションでは、JDK8には永久生成の概念がないため、これらの2つの例はJDK8の下での予想される効果を達成しなかったと述べました。 JDK8では、メソッド領域にメモリオーバーフローのようなエラーはありますか?もちろん、いくつか。 JDK8では、Metaspaceエリアを使用してクラス関連情報を保存するため、Metaspaceが不十分な場合はJava.lang.outofMemoryError:Metaspace Exceptionがスローされます。
上記の例を例として例として見てみましょう。
// vm args:-xx:maxmetaspacesize = 10mpublic class methodareaoomtest {public static void main(string [] args){while(true){enchancer enthancer = new Enhancer(); Enhancer.setsuperclass(methodareaoomtest.class); Enhancer.SetUseCache(false); Enhancer.setCallback(new MethodEnterceptor(){public object intercept(Object o、Method Method、Objects、MethodProxy MethodProxy)Throws {return MethodProxy.Invokesuper(o、objects);}}); Enhancer.create(); }}}この例のコード部分は変更されていません。唯一の違いは、JDK8を使用してこのコードを実行し、パラメーター-XX:Maxmetaspacesize = 10mを設定する必要があることです。このパラメーターは、Metaspaceの最大サイズが10mであることをJVMに伝えます。
次に、JDK8を使用してこの例をコンパイルして実行し、次の例外を出力します。
>>> java -jar -xx:maxmetaspacesize = 10m Target/test -1.0-snapshot.jarexception in thread "main" java.lang.outofmemoryerror:net.sf.cglib.core.abstractclassgenerator.generate(abstractclassgenerator.java:345) net.sf.cglib.enhancer.generate(enthancer.java:492)at net.sf.cglib.core.abstractclassgenerator $ classloaderdata.get(abstractclassgenerator.java:114)at net.sf.cglib.core.abstractclassgenerator.create(abstractclassgenerator.java:291)at net.sf.sf.cglib.proxy.enhancer.createhelper(encher.java:480)at net.sf.cglib.proxy.enhancer.crecner.clib.clib.clib.clib.clib.proxy.enhancer.cleater. com.test.methodareaoomtest.main(methodareaoomtest.java:22)
要約します
上記は、この記事の一般的なメモリオーバーフローの例外とコードの例に関するすべてです。私はそれがすべての人に役立つことを願っています。興味のある友人は、このサイトの他の関連トピックを引き続き参照できます。欠点がある場合は、それを指摘するためにメッセージを残してください。このサイトへのご支援をありがとうございました!