Запускает ли выбрасывание OutOfMemoryError дамп кучи, или память действительно должна быть исчерпана?

#java

#java

Вопрос:

Запускает ли выбрасывание OutOfMemoryError дамп кучи, или память действительно должна быть исчерпана?

Другими словами, будет ли создан дамп кучи, если я:

 throw new java.lang.OutOfMemoryError();
  

и установили

 -XX: HeapDumpOnOutOfMemoryError
  

Это универсально верно для всех JVM, или это, вероятно, зависит от конкретного поставщика?

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

Комментарии:

1. Я не понимаю, какое отношение ваш вопрос имеет к вашей проблеме

2. Он завершает работу JVM с OutOfMemoryError, но записывает ли он файл дампа, если он искусственно вызван подобным образом? Я пытаюсь протестировать дамп кучи, который иногда не записывается на диск при реальных обстоятельствах OOME.

3. В документации к самой опции в качестве примера показано выделение гигантского объекта, поэтому, вероятно, простого выбрасывания недостаточно. Как насчет выделения гигантского объекта?

4. Обратите внимание, что -XX: HeapDumpOnOutOfMemoryError записывается дамп кучи только в первом ООМ

5. gist.github.com/mosheeshel/0da62975c31e328721341439b3ee902a <- Пример ConsumeHeap

Ответ №1:

Поскольку в документации об этом не сказано, и это может зависеть, а может и не зависеть от конкретного поставщика, я бы просто создал большой объект для принудительного выполнения OOME.

Я использовал этот простой Runnable для создания потока, вызывающего OOME, когда мне нужно было:

 private static class OOMRunnable implements Runnable {

    private static final int ALLOCATE_STEP_SIZE = 1_000_000;

    @Override
    public void run() {
        long bytesUsed = 0L;
        List<long[]> eatingMemory = new ArrayList<>();

        while (true) {
            eatingMemory.add(new long[ALLOCATE_STEP_SIZE]);
            bytesUsed  = Long.BYTES * ALLOCATE_STEP_SIZE;

            System.out.printf("%d MB allocated%n", bytesUsed / 1_000_000);
        }
    }
}