2011-01-24 38 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); 
     } 
    } 
} 
相關問題