Цитирование Руководство по поиску и устранению неисправностей для Java SE 6 с HotSpot VM
3.1.3 Подробное сообщение: Requested array size exceeds VM limit
(встроенный жирный шрифт - мой):
Подробное сообщение Requested array size exceeds VM limit
указывает, что приложение (или API, используемые этим приложением) пытались выделить массив, размер которого больше размера кучи.Например, если приложение пытается выделить массив размером 512 МБ, но максимальный размер кучи равен 256 МБ, то будет выдано OutOfMemoryError
с причиной Requested array size exceeds VM limit
.В большинстве случаев проблема заключается либо в проблеме конфигурации (размер кучи слишком мал), либо ошибке, приводящей к тому, что приложение пытается создать огромный массив , например, когда числоэлементов в массиве вычисляются с использованием алгоритма, который вычисляет неправильный размер.
ОБНОВЛЕНИЕ: поощряется @ Pacerier Я провел небольшое быстрое тестирование.Я написал пример программы:
public class VmLimitTest {
public static final int SIZE = 2;
public static void main(String[] args) throws InterruptedException {
while(true) {
byte[] a = new byte[SIZE * 1024 * 1024];
TimeUnit.MILLISECONDS.sleep(10);
}
}
}
И запустил ее со следующими параметрами JVM:
-Xms192m -Xmx192m -XX:NewRatio=2 -XX:SurvivorRatio=6 -XX:+PrintGCDetails
Вот что они означают:
- Веськуча - 192 МБ (
-Xms192m -Xmx192m
) - Пространство молодого поколения (eden + Survivor) - 64 МБ, старого поколения - 128 МБ (
-XX:NewRatio=2
) - Каждое пространство для выживших (издва) равен 8 МБ, поэтому 48 МБ оставлено для eden (соотношение 1: 6,
-XX:SurvivorRatio=6
)
Во время тестирования я обнаружил следующее:
- ЕслиВновь созданный массив может уместиться в Eden (менее 48 МБ), программа работает нормально
- Удивительно, но когда размер массива превышает размер Eden, но может вписаться в Eden и одно пространство оставшегося в живых (между 48 и 56 МиБ), JVM может выделить один объект как для eden, так и для оставшегося в живых (перекрывая две области).Neat!
- Как только размер массива превысит eden + единственный оставшийся в живых (выше 56 MiB), вновь созданный объект помещается непосредственно в старое поколение, минуя пространства eden и Survivor.Это также означает, что внезапно полный GC выполняется все время - очень плохо!
- Я могу легко выделить 127 МБ данных, но при попытке выделить 129 МБ будет выброшено
OutOfMemoryError: Java heap space
Это нижняя строка - вы не можете создать объект размером больше старого поколения.Попытка сделать это приведет к ошибке OutOfMemoryError: Java heap space
.Так, когда мы можем ожидать ужасного Requested array size exceeds VM limit
?
Я попытался запустить ту же программу с гораздо большими объектами.Достигнув предела длины массива, я переключился на long[]
и мог легко подняться до 7 ГиБ.С объявлением о максимальном объеме кучи в 128 МБ JVM все еще выбрасывает OutOfMemoryError: Java heap space
(!). Мне удалось вызвать ошибку OutOfMemoryError: Requested array size exceeds VM limit
, пытаясь выделить 8 ГиБ в одном объекте.Я проверил это на 32-битном компьютере Linux с 3 ГБ физической памяти и 1 ГБ подкачки.
При этом вы, вероятно, никогда не попадете в эту ошибку.Документация кажется неточной / устаревшей, но она верна в одном заключении: это, вероятно, ошибка , поскольку создание таких огромных массивов очень редко.