Интересный вопрос :-).В то время как другие дали хорошие объяснения теоретических аспектов, я решил попробовать это.Это на Oracle JDK 1.6.0_26, Windows 7 64 бит.
Настройка теста
Я написал простую программу для исчерпания памяти (см. Ниже).
Программа просто создает статический java.util.List
и продолжает вставлять в него свежие строки, пока не будет выдано OOM.Затем он ловит его и продолжает вставлять в бесконечный цикл (плохая JVM ...).
Результат теста
Как видно из результатов, первые четырераз OOME выбрасывается, он идет с трассировкой стека.После этого последующие OOME выдают java.lang.OutOfMemoryError: Java heap space
, только если вызван printStackTrace()
.
Так что, очевидно, JVM пытается распечатать трассировку стека, если это возможно, но если памяти действительно мало, она просто пропускаетtrace, как и в других ответах.
Также интересен хэш-код OOME.Обратите внимание, что первые несколько OOME имеют разные хэши.Как только JVM начинает пропускать трассировки стека, хэш всегда одинаков.Это говорит о том, что JVM будет использовать свежие (предварительно выделенные?) Экземпляры OOME как можно дольше, но если push придет к пушу, он просто повторно использует тот же экземпляр, а не будет ничего бросать.
Вывод
Примечание. Я обрезал некоторые трассировки стека, чтобы сделать вывод более легким для чтения ("[...]").
iteration 0
iteration 100000
iteration 200000
iteration 300000
iteration 400000
iteration 500000
iteration 600000
iteration 700000
iteration 800000
iteration 900000
iteration 1000000
iteration 1100000
iteration 1200000
iteration 1300000
iteration 1400000
iteration 1500000
Ouch: java.lang.OutOfMemoryError: Java heap space; hash: 1069480624
Keep on trying...
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
at java.util.Arrays.copyOf(Unknown Source)
at java.util.ArrayList.ensureCapacity(Unknown Source)
at java.util.ArrayList.add(Unknown Source)
at testsl.Div.gobbleUpMemory(Div.java:23)
at testsl.Div.exhaustMemory(Div.java:12)
at testsl.Div.main(Div.java:7)
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
[...]
Ouch: java.lang.OutOfMemoryError: Java heap space; hash: 616699029
Keep on trying...
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
[...]
Ouch: java.lang.OutOfMemoryError: Java heap space; hash: 2136955031
Keep on trying...
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
[...]
Ouch: java.lang.OutOfMemoryError: Java heap space; hash: 1535562945
Keep on trying...
java.lang.OutOfMemoryError: Java heap space
Ouch: java.lang.OutOfMemoryError: Java heap space; hash: 1734048134
Keep on trying...
Ouch: java.lang.OutOfMemoryError: Java heap space; hash: 1734048134
Keep on trying...
java.lang.OutOfMemoryError: Java heap space
Ouch: java.lang.OutOfMemoryError: Java heap space; hash: 1734048134
Keep on trying...
[...]
Программа
public class Div{
static java.util.List<String> list = new java.util.ArrayList<String>();
public static void main(String[] args) {
exhaustMemory();
}
private static void exhaustMemory() {
try {
gobbleUpMemory();
} catch (OutOfMemoryError e) {
System.out.println("Ouch: " + e+"; hash: "+e.hashCode());
e.printStackTrace();
System.out.println("Keep on trying...");
exhaustMemory();
}
}
private static void gobbleUpMemory() {
for (int i = 0; i < 10000000; i++) {
list.add(new String("some random long string; use constructor to force new instance"));
if (i % 10000000== 0) {
System.out.println("iteration "+i);
}
}
}
}