Могу ли я столкнуться с java.lang.OutOfMemoryError даже без недостатка памяти? - PullRequest
5 голосов
/ 29 января 2012

Я читал Открытие java.lang.Out OfMemoryError и мне было интересно, правильно ли я понял.Верно ли, что если Java VM выдает

java.lang.OutOfMemoryError: размер запрошенного массива превышает ограничение VM

Это означает, что VM имеетотклонил создание массива из-за того, что он превысил предопределенный лимит (превысил число виртуальных машин), а не , поскольку у меня не хватило памяти в пространстве кучи?

Правильно ли я сказал, что java.lang.OutOfMemoryError: Requested array size exceeds VM limit не указывает на нехватку памяти?

Даже если у меня неограничено памяти везде , виртуальная машина Java все еще может выдатьjava.lang.OutOfMemoryError: Requested array size exceeds VM limit если мне не нравится мой запрос на создание массива размером n ?

Ответы [ 2 ]

9 голосов
/ 29 января 2012

Цитирование Руководство по поиску и устранению неисправностей для 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 ГБ подкачки.

При этом вы, вероятно, никогда не попадете в эту ошибку.Документация кажется неточной / устаревшей, но она верна в одном заключении: это, вероятно, ошибка , поскольку создание таких огромных массивов очень редко.

1 голос
/ 29 января 2012

Указывает на недостаток памяти в куче. В других областях может быть много доступной памяти, но недостаточно памяти для создания запрошенного объекта (может быть массив (или) простая строка). Вот хороший блог на эту тему .

...