Javaヒープオーバーフロー
Javaヒープは、オブジェクトインスタンスを格納するために使用されます。オブジェクトの数がヒープの最大容量まで増えると、メモリオーバーフローが発生します。
heap-Xmsの最小値heap-Xmxの最大値
アイデアは仮想マシンのパラメータを構成します
static class OOMObject
{
}
public static void main(String[] args)
{
List<OOMObject> list = new ArrayList<>();
while (true)
{
list.add(new OOMObject());
}
}
運用結果
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid16012.hprof ...
Heap dump file created [29135766 bytes in 0.072 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:265)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
at java.util.ArrayList.add(ArrayList.java:462)
at Scratch.main(scratch.java:44)
仮想マシンスタックとローカルメソッドスタックのオーバーフロー
パラメータ-Xssは、スタック容量を変更します。
- スレッドによって要求されたスタックの深さが仮想マシンによって許可された最大の深さよりも大きい場合、「StackOverflowError」例外がスローされます。
- 仮想マシンスタックのメモリが動的拡張を許可している場合、拡張スタック容量が十分なメモリに適用できないと、OutOfMemoryError例外がスローされます。
メソッド領域とランタイム定数プールのオーバーフロー
実行時定数プールはメソッド領域の一部です。
仮想マシンパラメータ-XX:PermSize、-XX:MaxPermSizeは、永続的な生成のサイズを制限します。
JDK6以前のHotSpot仮想マシンの定数プールは永続世代に割り当てられ、JDK7以降の定数プールはJavaヒープに割り当てられます。したがって、JDK6より前では、仮想マシンは永続的な生成のサイズを制限することでOutOfMemoryError例外をスローできます。JDK7以降では、ヒープスペースを制限する必要があります。
String :: intern():文字列定数プールにこのStringオブジェクトと等しい文字列がすでに含まれている場合は、プール内の文字列を表すStringオブジェクトへの参照を返します。それ以外の場合は、このStringオブジェクトに含まれている文字を返します。文字列が定数プールに追加され、このStringオブジェクトへの参照が返されます。
public static void main(String[] args)
{
String str1 = new StringBuilder("计算机").append("网络工程").toString();
System.out.println(str1.intern() == str1);
String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern() == str2);
}
返回结果:
JDK7及以上
true
false
JDK6
false
false
理由:JDK6では、初めて検出された文字列は永続世代に格納され、戻り値は永続世代の参照であり、StringBuilderはJavaヒープで作成されたオブジェクトであるため、参照ではありません。
JDK7以降の定数プールはJavaヒープに移動されました。参照インスタンスの最初の出現を記録するだけでよいため、intern()によって返される参照と、StringBuilderによって作成された文字列インスタンスが使用されます。str2は、java文字が初めて検出されないため(sun.misc.Versionクラスのロード時に定数プールにロードされる)、falseを返します。
JDK8の後、メタスペースが永続的な世代に置き換わります。
パラメータ-XX:MaxMetaspaceSizeは、メタスペースの最大値を設定します。デフォルト値は-1です。これは、制限がなく、ローカルメモリのみに制限されることを意味します。
-XX:MetaspaceSize:メタスペースの初期サイズをバイト単位で指定します。この値に達すると、タイプのアンロード用のガベージコレクションがトリガーされ、コレクターが値を調整します。大量のスペースが解放される場合は値を適切に下げる必要があり、少量のスペースが解放される場合は適切に減らすことができます。
-XX:MinMetaspaceFreeRatio:この関数は、ガベージ収集後の最小メタスペースの残り容量のパーセンテージを制御することです。これにより、メタスペースが不十分なためにガベージ収集の頻度を減らすことができます。
ネイティブダイレクトメモリオーバーフロー
直接メモリは-XX:ManDirectMemorySizeで指定されます。デフォルトおよびヒープメモリを常に指定しないでください(-Xmx)