Что делать, если новая ошибка?

В С++ и С#, когда новый не может выделить достаточную память, он выдает исключение.

Я не мог найти никакой информации о новом поведении на Java. Итак, что произойдет, если новый сбой в Java (недостаточно памяти)?

Ответ 1

Предполагая, что вы конкретно подразумеваете отказ в распределении памяти, тогда он должен бросить OutOfMemoryError

Брошенный, когда виртуальная машина Java не может выделить объект, поскольку он неактивен, и сборщик мусора не может сделать доступной больше.

Как и все подклассы Error, это обычно не восстанавливаемое условие, даже если технически вы можете его поймать:

Ошибка - это подкласс Throwable, который указывает на серьезные проблемы, которые разумное приложение не должно пытаться поймать. Большинство таких ошибок являются ненормальными условиями. Ошибка ThreadDeath, хотя и является "нормальным" условием, также является подклассом Error, поскольку большинство приложений не должны пытаться ее поймать.

Не требуется метод объявлять в свойстве throws любые подклассы Error, которые могут быть выбраны во время выполнения метода, но не пойманы, поскольку эти ошибки являются ненормальными условиями, которые никогда не должны возникать.

Ответ 2

Когда Java не может получить достаточное количество памяти для выделения объекта, вы получите OutOfMemoryError.

На практике исключение может занять довольно много времени, чтобы быть фактически брошенным JVM. Когда проблема связана с памятью, JVM сначала попытается собрать как можно больше памяти. В зависимости от конфигурации JVM (параметры GC и максимальной памяти кучи) цикл GC может занимать от нескольких секунд до нескольких минут, а Xmx устанавливается в несколько гигабайт. Хуже того, в зависимости от требуемой памяти, JVM может выполнять несколько циклов GC перед выбросом исключения.

Когда исключение является броском, оно обрабатывается как любое неперехваченное исключение. Таким образом, он будет распространяться на вершину вызывающего стека потока, где было создано исключение. Поскольку исключение является неотображенным, поток будет отображать stacktrace на System.err перед смертью. Все это. В однопоточной программе это приведет к выходу программы. В многопоточной программе этот поток смерти может освободить достаточно памяти, чтобы программа продолжала работать в неустойчивой конфигурации.

Моя рекомендация, если вы обеспокоены проблемой памяти, заключается в том, что вы должны зарегистрироваться и UncaughtExceptionHandler, чтобы убить вашу программу, когда возникает проблема с памятью так как это, безусловно, лучше остановить вашу программу, чем позволить ей работать в состоянии undefined, не зная кого-либо.

Вы можете прочитать следующие статьи Хайнца Кабуца по теме:

Ответ 3

Если у вас действительно недостаточно памяти, выдается OutOfMemoryError. Любое исключение может быть вызвано самим конструктором.

Ответ 4

Немного больше на OOME.

/*License - LGPL
<h3>Recovery from an OutOfMemory Error</h3>
<p>The JavaDocs for Error state, in the first sentence..

<blockquote>"An Error is a subclass of Throwable that indicates
serious problems that a reasonable application should
not try to catch."</blockquote>

<p>This advice has led to the fallacy that an OutOfMemoryError
should not be caught and dealt with.  But this demo. shows
that it is quite easy to recover to the point of providing
the user with meaningful information, and advice on how to
proceed.

<p>I aim to make my applications 'unreasonable'.  ;-)
*/

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JOptionPane;
import javax.swing.JDialog;
import javax.swing.Timer;

import javax.swing.border.EmptyBorder;

import java.util.ArrayList;

/** A demo. showing recovery from an OutOfMemoryError.
Our options once an OOME is encountered are relatively
few, but we can still warn the end user and provide
advice on how to correct the problem.
@author Andrew Thompson */
public class MemoryRecoveryTest {

    public static void main(String[] args) {
        // reserve a buffer of memory
        byte[] buffer = new byte[2^10];
        ArrayList<Object> list = new ArrayList<Object>();
        final JProgressBar memory = new JProgressBar(
            0,
            (int)Runtime.getRuntime().totalMemory());
        ActionListener listener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                memory.setValue(
                    (int)Runtime.getRuntime().freeMemory() );
            }
        };
        Timer timer = new Timer(500, listener);
        timer.start();

        JDialog dialog = new JDialog();
        dialog.setTitle("Available Memory");
        JPanel memoryPanel = new JPanel();
        memoryPanel.add(memory);
        memoryPanel.setBorder(new EmptyBorder(25,25,25,25));
        dialog.add( memoryPanel );
        dialog.pack();
        dialog.setLocationRelativeTo(null);
        dialog.setVisible(true);
        dialog.addWindowListener( new WindowAdapter(){
            @Override
            public void windowClosing(WindowEvent we) {
                System.exit(0);
            }
        } );

        // prepare a memory warning panel in advance
        JPanel memoryWarning = new JPanel();
        memoryWarning.add( new JLabel(
            "<HTML><BODY>There is not enough memory to" +
            " complete the task!<BR> Use a variant " +
            " of the application that assigns more memory.") );

        try {
            // do our 'memory intensive' task
            while(true) {
                list.add( new Object() );
            }
        } catch(OutOfMemoryError oome) {
            // provide the VM with some memory 'breathing space'
            // by clearing the buffer
            buffer = null;
            // tell the user what went wrong, and how to fix it
            JOptionPane.showMessageDialog(
                dialog,
                memoryWarning,
                "Out of Memory!",
                JOptionPane.ERROR_MESSAGE);
        }
    }
}

Ответ 5

Вы можете поймать OutOfMemoryExceptions, но не рекомендуется. Однако, если это не проблема с кодированием/дизайном, сборщик мусора должен заботиться об управлении кучей.

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

// Get current size of heap in bytes
long heapSize = Runtime.getRuntime().totalMemory();

// Get maximum size of heap in bytes. The heap cannot grow beyond this size.
// Any attempt will result in an OutOfMemoryException.
long heapMaxSize = Runtime.getRuntime().maxMemory();

// Get amount of free memory within the heap in bytes. This size will increase
// after garbage collection and decrease as new objects are created.
long heapFreeSize = Runtime.getRuntime().freeMemory();