ओओएम को पकड़ा जा सकता है लेकिन आम तौर पर बेकार होने वाला है, इस पर निर्भर करता है कि क्या जेवीएम कुछ वस्तुओं को इकट्ठा करने में सक्षम होता है, जब पकड़ में आ जाता है, और उस समय तक कितनी ढेर मेमोरी बच जाती है।
उदाहरण: मेरे जेवीएम में, यह कार्यक्रम पूरा होने तक चलता है:
import java.util.LinkedList;
import java.util.List;
public class OOMErrorTest {
public static void main(String[] args) {
List<Long> ll = new LinkedList<Long>();
try {
long l = 0;
while(true){
ll.add(new Long(l++));
}
} catch(OutOfMemoryError oome){
System.out.println("Error catched!!");
}
System.out.println("Test finished");
}
}
हालाँकि, कैच पर केवल एक लाइन जोड़ने से आपको पता चल जाएगा कि मैं किस बारे में बात कर रहा हूँ:
import java.util.LinkedList;
import java.util.List;
public class OOMErrorTest {
public static void main(String[] args) {
List<Long> ll = new LinkedList<Long>();
try {
long l = 0;
while(true){
ll.add(new Long(l++));
}
} catch(OutOfMemoryError oome){
System.out.println("Error catched!!");
System.out.println("size:" +ll.size());
}
System.out.println("Test finished");
}
}
पहला कार्यक्रम ठीक चलता है क्योंकि जब पकड़ में आता है, तो जेवीएम यह पता लगाता है कि सूची का अब उपयोग नहीं किया जा रहा है (यह पता लगाना संकलन समय पर किया गया अनुकूलन भी हो सकता है)। इसलिए जब हम प्रिंट स्टेटमेंट तक पहुंचते हैं, तो ढेर मेमोरी को लगभग पूरी तरह से मुक्त कर दिया गया है, इसलिए अब जारी रखने के लिए हमारे पास पैंतरेबाज़ी का एक विस्तृत मार्जिन है। यह सबसे अच्छा मामला है।
हालाँकि, यदि कोड को व्यवस्थित ll
किया जाता है जैसे कि OOME पकड़े जाने के बाद सूची का उपयोग किया जाता है, तो JVM इसे एकत्र करने में असमर्थ है। यह दूसरी स्निपेट में होता है। OOME, एक नई लॉन्ग क्रिएशन द्वारा ट्रिगर किया गया है, पकड़ा गया है, लेकिन जल्द ही हम एक नया ऑब्जेक्ट ( System.out,println
लाइन में एक स्ट्रिंग ) बना रहे हैं, और ढेर लगभग पूरा हो गया है, इसलिए एक नया OOME फेंक दिया गया है। यह सबसे खराब स्थिति है: हमने एक नई वस्तु बनाने की कोशिश की, हम विफल रहे, हमने ओओएम को पकड़ लिया, हां, लेकिन अब नए हीप मेमोरी (जैसे: एक नई वस्तु बनाने) की आवश्यकता वाले पहले निर्देश एक नया ओओएम फेंक देंगे। इसके बारे में सोचें, हम इस बिंदु पर और क्या कर सकते हैं कि इतनी कम मेमोरी बची है? शायद बस बाहर निकल रहा है। इसलिए बेकार है।
जेवीएम के संसाधनों को इकट्ठा न करने के कारणों में, एक वास्तव में डरावना है: अन्य थ्रेड्स के साथ एक साझा संसाधन भी इसका उपयोग कर रहा है। मस्तिष्क वाला कोई भी व्यक्ति देख सकता है कि अगर किसी भी तरह के गैर-प्रायोगिक ऐप पर डाला जाए तो ओओएम कितना खतरनाक हो सकता है।
मैं एक Windows x86 32bit JVM (JRE6) का उपयोग कर रहा हूं। प्रत्येक जावा ऐप के लिए डिफ़ॉल्ट मेमोरी 64 एमबी है।