2011-01-24 43 views
11

सी ++ और सी # में जब नया एनोट मेमोरी आवंटित करने में सक्षम नहीं है तो यह अपवाद फेंकता है।क्या होगा यदि नया विफल रहता है?

मुझे जावा में नए व्यवहार के बारे में कोई जानकारी नहीं मिली। तो जावा में नया असफल होने पर क्या होगा (पर्याप्त स्मृति नहीं)?

उत्तर

23

मान लिया जाये कि आप विशेष रूप से स्मृति आवंटन की विफलता का मतलब , तो यह फेंक चाहिए क्योंकि यह स्मृति से बाहर है OutOfMemoryError

फेंक दिया जब जावा वर्चुअल मशीन एक वस्तु आवंटित नहीं कर सकता है, और कोई अधिक स्मृति हो सकता है कचरा कलेक्टर द्वारा उपलब्ध कराया गया।

Error के सभी उपवर्गों की तरह, यह आमतौर पर एक गैर वसूली योग्य हालत है, यहां तक ​​कि तकनीकी रूप से यदि आप कर सकते हैं पकड़ यह:

कोई त्रुटि फेंकने योग्य का एक उपवर्ग है कि एक उचित गंभीर समस्या का संकेत करता है आवेदन पकड़ने की कोशिश नहीं करनी चाहिए। ऐसी अधिकांश त्रुटियां असामान्य स्थितियां हैं। थ्रेडडिथ त्रुटि, हालांकि "सामान्य" स्थिति, त्रुटि का उप-वर्ग भी है क्योंकि अधिकांश अनुप्रयोगों को इसे पकड़ने की कोशिश नहीं करनी चाहिए।

किसी फंक्शन को घोषित करने के लिए किसी विधि के किसी भी उप-वर्ग को घोषित करने की आवश्यकता नहीं है जिसे विधि के निष्पादन के दौरान फेंक दिया जा सकता है लेकिन पकड़ा नहीं जाता है, क्योंकि ये त्रुटियां असामान्य स्थितियां होती हैं जो कभी नहीं होनी चाहिए।

+1

कोड को लिखना संभव है जो इस स्थिति से ठीक हो जाता है, बशर्ते आपके पास ज्ञात समस्या के लिए इसे पकड़ने का एक अच्छा कारण हो। यह शायद ही कभी एक अच्छा विचार है और उपभोग की गई स्मृति को कम करने या अधिकतम मेमोरी को बढ़ाने से आमतौर पर सबसे अच्छा विकल्प होता है। –

2

यदि आपके पास वास्तव में पर्याप्त स्मृति नहीं है OutOfMemoryError फेंक दिया गया है। इसके अलावा किसी भी अपवाद को कन्स्ट्रक्टर द्वारा ही फेंक दिया जा सकता है।

1

आप आउटऑफमेमरी अपवादों को पकड़ सकते हैं लेकिन अनुशंसित नहीं हैं। हालांकि, जब तक कि यह कोडिंग/डिज़ाइन समस्या न हो - कचरा कलेक्टर को ढेर के प्रबंधन का ख्याल रखना चाहिए।

यदि आपको लगता है कि आप बड़ी मात्रा में डेटा प्रोसेसिंग कर रहे हैं और मेमोरी चला सकते हैं तो आप हमेशा निष्पादन शुरू करने से पहले उपलब्ध खाली स्थान की जांच कर सकते हैं (इस 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

ओओएम न केवल कोडिंग/डिज़ाइन समस्याओं के कारण हैं, कम से कम उन लोगों को जिन्हें आप हमेशा नियंत्रित कर सकते हैं। मशहूर तृतीय पक्ष एपीआई में मेमोरी-लीक, जो कि जावा के जीवन (और जो निश्चित रूप से जारी रहेगा) के दौरान काफी आम हैं ... – SyntaxT3rr0r

+2

तृतीय पक्ष एपीआई की निश्चित पसंद मेरी राय में डिजाइन का हिस्सा हैं। – CoolBeans

4

जब जावा के लिए पर्याप्त स्मृति एक वस्तु आप एक OutOfMemoryError मिलेगा आवंटित करने के लिए नहीं मिल सकता है।

प्रैक्टिस में अपवाद को वास्तव में JVM द्वारा फेंकने में कुछ समय लग सकता है। जब स्मृति समस्या का सामना करना पड़ता है, तो जेवीएम पहले जितना संभव हो उतना मेमोरी कचरा करने की कोशिश करेगा। जेवीएम कॉन्फ़िगरेशन (जीसी पैरामीटर और अधिकतम ढेर मेमोरी) के आधार पर, एक जीसी चक्र कई मिनटों में एक्सएमएक्स सेट के साथ कई गीगाबाइट सेट कर सकता है। इससे भी बदतर, स्मृति की आवश्यकता के आधार पर, जेवीएम अपवाद फेंकने से पहले कई जीसी चक्र कर सकता है।

जब अपवाद फेंक दिया जाता है, तो इसे किसी भी अपरिपक्व अपवाद के रूप में संसाधित किया जाता है। जैसे ही यह थ्रेड के कॉलिंग स्टैक के शीर्ष पर प्रचार करेगा जहां अपवाद उठाया गया था। चूंकि अपवाद बेकार है, इसलिए धागा मरने से पहले 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); 
     } 
    } 
} 
+0

मैं तर्क दूंगा कि यह एक झूठ नहीं है - http://stackoverflow.com/a/6213636/139985 देखें –

संबंधित मुद्दे