如果新的失败怎么办?

时间:2011-01-24 17:59:07

标签: java memory-management

在C ++和C#中,当new无法分配内存时,它会抛出异常。

我在Java中找不到有关new的行为的任何信息。 那么如果新的Java失败(没有足够的内存)会发生什么?

5 个答案:

答案 0 :(得分:25)

假设您具体意味着内存分配失败,那么它应该抛出OutOfMemoryError

  

当Java虚拟机因内存不足而无法分配对象时抛出,垃圾收集器不再提供更多内存。

Error的所有子类一样,它通常是不可恢复的条件,即使技术上你可以捕获它:

  

错误是Throwable的子类,表示合理的应用程序不应该尝试捕获的严重问题。大多数此类错误都是异常情况。 ThreadDeath错误虽然是“正常”条件,但也是Error的子类,因为大多数应用程序都不应该尝试捕获它。

     

不需要在throws子句中声明任何可能在方法执行期间抛出但未捕获的Error子类,因为这些错误是永远不会发生的异常情况。

答案 1 :(得分:4)

当Java无法获得足够的内存来分配对象时,您将获得OutOfMemoryError

实际上,JVM实际抛出异常可能需要很长时间。当遇到内存问题时,JVM将首先尝试尽可能多地浪费内存。根据JVM配置(GC参数和最大堆内存),GC周期可能需要几秒到几分钟,而Xmx设置为几千兆字节。更糟糕的是,根据所需的内存,JVM可以在抛出异常之前执行几个GC周期。

抛出异常时,它会被处理为任何未捕获的异常。因此,它将传播到引发异常的线程的调用堆栈的顶部。由于异常未被捕获,该线程将在死亡前在System.err上显示堆栈跟踪。就这样。在单线程程序中,这将导致程序退出。在一个多线程程序中,这个线程死亡可以释放足够的内存,让程序继续在不稳定的配置中运行。

我建议如果你担心内存问题,你应该注册并UncaughtExceptionHandler在出现内存问题时杀死你的程序,因为停止你的程序肯定比让它在一个未定义的状态下工作更好没有人知道。

您可以阅读Heinz Kabutz关于此主题的以下文章:

答案 2 :(得分:2)

如果你真的没有足够的内存,则抛出OutOfMemoryError。 此外,构造函数本身也可能抛出任何异常。

答案 3 :(得分:2)

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);
        }
    }
}

答案 4 :(得分:1)

您可以捕获OutOfMemoryExceptions但不推荐。但是,除非它是编码/设计问题 - 垃圾收集器应该负责管理堆。

如果您认为您将进行大量数据处理并且可能会运行内存,那么您可以在开始执行之前检查可用空间(从此link复制代码段)。

// 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();