2011-01-24 63 views
11

在C++和C#中,当新的不能分配足够的内存时它会抛出异常。如果新建失败会怎么样?

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

回答

23

假设你专门意味着内存分配失败,那么它应该抛出时,Java虚拟机无法分配一个对象,因为它是内存不足OutOfMemoryError

抛出,并没有更多的内存可由垃圾收集器提供。

喜欢Error所有子类,它通常是不可恢复的情况,即使在技术上你可以抓住它:

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

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

+1

如果您有足够的理由去解决已知问题,那么可以编写从此条件恢复的代码。这很少是一个好主意,减少内存消耗或增加最大内存通常是最佳选择。 – 2011-01-24 20:52:30

2

如果你真的没有足够的内存OutOfMemoryError被抛出。 也可以由构造函数本身抛出任何异常。

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(); 
+0

OOM不仅是由于编码/设计问题,至少不是你可以随时控制的。在著名的第三方的API,Java的生活(和谁肯定会继续),在此期间,已经非常普遍,内存泄漏想到......第三方的API – SyntaxT3rr0r 2011-01-24 18:24:37

+2

当然选择是在我看来,设计的一部分。 – CoolBeans 2011-01-24 19:01:20

4

Java的时候无法获得足够的内存来分配一个对象,你会得到一个OutOfMemoryError

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

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

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

您可以在主题阅读亨氏Kabutz下面的文章:

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); 
     } 
    } 
} 
相关问题