2010-06-17 8 views
37
  1. JVM पुन: प्रारंभ करने के बिना एक OutOfMemoryError से उबरने कर सकते हैं कि इसे और अधिक वस्तु आवंटन अनुरोध में आते हैं इससे पहले कि जी सी को चलाने के लिए एक मौका हो जाता है बिना एक OutOfMemoryError से उबरने कर सकते हैं?JVM पुन: प्रारंभ करने

  2. विभिन्न JVM कार्यान्वयन इस पहलू में भिन्न होते हैं?

मेरा प्रश्न JVM पुनर्प्राप्ति के बारे में है और उपयोगकर्ता प्रोग्राम त्रुटि को पकड़कर पुनर्प्राप्त करने का प्रयास नहीं कर रहा है। दूसरे शब्दों में यदि किसी ओओएमई को किसी एप्लिकेशन सर्वर (jboss/websphere/..) में फेंक दिया जाता है, तो क्या मैं को पुनरारंभ करने के लिए करता हूं? या यदि मैं बिना किसी समस्या के काम करता हूं तो मैं इसे चलाने देता हूं।

+0

भी http://stackoverflow.com/questions/2679330/catching-java-lang-outofmemoryerror – Raedwald

उत्तर

38

यह काम कर सकता है, लेकिन यह आमतौर पर एक बुरा विचार है। इस बात की कोई गारंटी नहीं है कि आपका आवेदन पुनर्प्राप्त करने में सफल होगा, या यह पता चलेगा कि यह सफल नहीं हुआ है या नहीं। उदाहरण के लिए:

  • वास्तव नहीं पर्याप्त स्मृति आरक्षित स्मृति के ब्लॉक जारी की तरह वसूली कदम उठाने के बाद भी अनुरोध किया कार्य करने के लिए हो सकता है। इस स्थिति में, आपका एप्लिकेशन एक लूप में फंस सकता है जहां यह बार-बार ठीक होने लगता है और फिर स्मृति से बाहर चला जाता है।

  • ओओएमई किसी भी धागे पर फेंक दिया जा सकता है। यदि किसी एप्लिकेशन थ्रेड या लाइब्रेरी को इसका सामना करने के लिए डिज़ाइन नहीं किया गया है, तो यह एक अपूर्ण या असंगत स्थिति में कुछ दीर्घकालिक डेटा संरचना छोड़ सकता है।

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

  • मान लीजिए कि थ्रेड अधिसूचना/प्रतीक्षा या कुछ उच्च स्तरीय तंत्र का उपयोग करके अन्य धागे के साथ सिंक्रनाइज़ करता है। यदि वह धागा ओओएमई से मर जाता है, तो अन्य धागे को सूचित करने के लिए इंतजार किया जा सकता है (आदि) जो कभी नहीं आते ... उदाहरण के लिए। इसके लिए डिजाइनिंग एप्लिकेशन को और अधिक जटिल बना सकता है।

सारांश में, डिजाइन, लागू करने और OOMEs से उबरने के लिए एक आवेदन पत्र का परीक्षण मुश्किल हो सकता है, खासकर अगर आवेदन (या ढांचा जिसमें यह चलाता है, या पुस्तकालयों का उपयोग करता है के किसी भी) बहु लड़ी है । ओओएमई को घातक त्रुटि के रूप में पेश करना बेहतर विचार है।

एक संबंधित सवाल का यह भी देखें my answer: -:

दूसरे शब्दों में एक OOME (एक आवेदन सर्वर में फेंक दिया जाता है, तो jboss/websphere/

संपादित इस फॉलोअप सवाल के जवाब में ..) क्या मैं को पुनरारंभ करना है?

नहीं, आप को पुनरारंभ नहीं करना है। लेकिन यह शायद बुद्धिमान है, विशेष रूप से यदि आपके पास यह जांचने का एक अच्छा/स्वचालित तरीका नहीं है कि सेवा सही तरीके से चल रही है।

जेवीएम ठीक ठीक हो जाएगा। लेकिन एप्लिकेशन सर्वर और एप्लिकेशन स्वयं इस स्थिति से निपटने के लिए कितनी अच्छी तरह डिजाइन किए गए हैं, इस पर निर्भर करता है कि यह ठीक हो सकता है या नहीं। (मेरा अनुभव यह है कि कुछ ऐप सर्वर इस से निपटने के लिए डिज़ाइन किए गए हैं, और ओओएमई से पुनर्प्राप्त करने के लिए एक जटिल अनुप्रयोग को डिजाइन और कार्यान्वित करना कठिन है, और इसे ठीक से परीक्षण करना भी कठिन है।)

संपादित 2

इस टिप्पणी के जवाब में:

"अन्य थ्रेड छोड़ा जा सकता है सूचनाएं दे इंतजार कर (आदि) कि कभी नहीं आ" वाकई? क्या मारे गए थ्रेड अपने ढेर को खारिज नहीं करेंगे, संसाधनों को जारी करते हुए, जैसे कि ताले लगाएंगे?

हाँ वास्तव में! पर विचार करें इस:

थ्रेड # 1 रन इस:

synchronized(lock) { 
     while (!someCondition) { 
      lock.wait(); 
     } 
    } 
    // ... 

थ्रेड # 2 रन इस: थ्रेड # 1 सूचित पर इंतज़ार कर रहा है, और थ्रेड # 2 एक OOME हो जाता है

synchronized(lock) { 
     // do stuff 
     lock.notify(); 
    } 

हैं // do something अनुभाग में, तो थ्रेड # 2 notify() कॉल नहीं करेगा, और थ्रेड # 1 हमेशा एक अधिसूचना के लिए प्रतीक्षा कर सकता है जो कभी नहीं होगा। निश्चित रूप से, थ्रेड # 2 को lock ऑब्जेक्ट पर mutex को रिलीज़ करने की गारंटी है ... लेकिन यह पर्याप्त नहीं है!

यदि थ्रेड द्वारा चलाया गया कोड अपवाद सुरक्षित नहीं है, जो एक और सामान्य समस्या है।

"अपवाद सुरक्षित" एक शब्द नहीं है जिसे मैंने सुना है (हालांकि मुझे पता है कि आपका क्या मतलब है)। जावा प्रोग्राम सामान्य रूप से अप्रत्याशित अपवादों के लिए लचीला होने के लिए डिज़ाइन नहीं किए जाते हैं। दरअसल, उपरोक्त की तरह एक परिदृश्य में, यह एप्लिकेशन अपवाद को सुरक्षित बनाने के लिए कहीं मुश्किल और असंभव के बीच होने की संभावना है।

आपको कुछ तंत्र की आवश्यकता होगी जिससे थ्रेड # 1 (ओओएमई के कारण) की विफलता थ्रेड # 2 के लिए एक अंतर-थ्रेड संचार विफलता अधिसूचना में बदल जाती है। Erlang यह करता है ... लेकिन जावा नहीं। Erlang में ऐसा करने का कारण यह है कि Erlang सख्त सीएसपी जैसी प्राइमेटिव का उपयोग करके संचार की प्रक्रिया करता है; यानी डेटा संरचनाओं का कोई साझाकरण नहीं है!

(ध्यान दें आप बस के बारे में कोई अप्रत्याशित अपवाद के लिए ऊपर समस्या हो सकता है कि ... बस Error अपवाद नहीं। जावा कोड के कुछ प्रकार के होते हैं, जहां एक अप्रत्याशित अपवाद से उबरने का प्रयास कर रहा खत्म होने की संभावना है बुरी तरह से।)

+0

"अन्य धागे को सूचित करने के लिए इंतजार किया जा सकता है (आदि) जो कभी नहीं आते" वास्तव में? क्या मारे गए थ्रेड अपने ढेर को खारिज नहीं करेंगे, संसाधनों को जारी करते हुए, जैसे कि ताले लगाएंगे? यदि थ्रेड द्वारा चलाया गया कोड अपवाद सुरक्षित नहीं है, जो एक और सामान्य समस्या है। – Raedwald

+0

"ओओएमई किसी भी थ्रेड पर फेंक दिया जा सकता है" और किसी भी समय, न केवल 'नए' पर। और इसमें उन स्थानों में शामिल है जो आपके प्रोग्राम को असंगत स्थिति में छोड़ देते हैं। Http://stackoverflow.com/questions/8728866/no-throw-virtualmachineerror- गारंटी – Raedwald

+0

आपके संपादन 2 के लिए मैं कहूंगा कि 'lock.wait();' समस्या है, ओओएमई स्वयं नहीं, क्योंकि किसी भी रनटाइम अपवाद के कारण एक ही व्यवहार हो सकता है। – SpaceTrucker

3

JVM OutOfMemoryError के किनारे पर जीसी चलाएगा। अगर जीसी बिल्कुल मदद नहीं करता है, तो जेवीएम ओओएमई फेंक देगा।

आप हालांकि catch कर सकते हैं और यदि आवश्यक हो तो वैकल्पिक पथ लें। try ब्लॉक के अंदर कोई भी आवंटन जीसीएड होगा।

चूंकि ओओएमई "बस" Error है जो आप केवल catch कर सकते हैं, मैं उम्मीद करता हूं कि विभिन्न जेवीएम कार्यान्वयन समान व्यवहार करेंगे। मैं कम से कम अनुभव से पुष्टि कर सकता हूं कि उपरोक्त सूर्य जेवीएम के लिए सच है।

यह भी देखें:

+0

देखें मैं इसे * उच्च * स्टैक पर पकड़ने की सिफारिश करेंगे। यानी कार्य की शुरुआत में। इस तरह, यह किसी भी डेटा को जीसी करने का प्रयास कर सकता है जो स्मृति के समय समाप्त होने पर "दायरे में" होता। "किसी भी सीन जेवीएम" के लिए – Killjoy1221

1

आप हालांकि इसकी सलाह नहीं दी जाती है कि आप की कोशिश इस परिदृश्य से उबरने के अपने बाधाओं बढ़ा सकते हैं। तुम क्या है स्टार्टअप thats अपनी वसूली का काम कर के लिए समर्पित पर स्मृति के कुछ निश्चित राशि पूर्व आवंटित, और जब आप यह OOM पकड़ने, बाहर शून्य है कि पूर्व आवंटित संदर्भ और आपअधिक उपयोग करने के लिए कुछ स्मृति होने की संभावना हो आपके रिकवरी अनुक्रम में।

मैं अलग JVM कार्यान्वयन के बारे में पता नहीं है।

1

किसी भी समझदार JVM केवल अगर वहाँ कुछ भी कचरा कलेक्टर कर सकते हैं एक OutOfMemoryError फेंक देते हैं। हालांकि, अगर आप स्टैक फ्रेम पर पर्याप्त आउटऑफमेमरी एरर को पकड़ते हैं तो यह संभवतः पर्याप्त हो सकता है कि कारण स्वयं पहुंच योग्य नहीं था और कचरा इकट्ठा किया गया था (जब तक कि वर्तमान थ्रेड में समस्या न हो)।

आम तौर पर फ्रेमवर्क जो अन्य सर्वर चलाते हैं, जैसे अनुप्रयोग सर्वर, ओएमई के चेहरे में जारी रखने का प्रयास करना समझ में आता है (जब तक यह उचित रूप से तीसरे पक्ष के कोड को छोड़ सकता है), लेकिन अन्यथा, सामान्य मामले में, वसूली शायद कुछ भी नहीं हुआ जैसे कि आगे बढ़ने की कोशिश करने के बजाए, उपयोगकर्ता को झुकाव और उपयोगकर्ता को क्यों बताना चाहिए।

अपने नए-नए अपडेट सवाल का जवाब करने के लिए: वहाँ आप सर्वर को बंद करने के अगर सब कुछ ठीक काम कर रहा है की जरूरत है सोचने के लिए कोई कारण नहीं है। जेबॉस के साथ मेरा अनुभव यह है कि जब तक ओएमई ने तैनाती को प्रभावित नहीं किया, तब तक चीजें ठीक काम करती हैं। कभी-कभी यदि आप बहुत गर्म तैनाती करते हैं तो जेबॉस परमजन स्पेस से बाहर चला जाता है। फिर वास्तव में स्थिति निराशाजनक है और तत्काल पुनरारंभ (जिसे मारने के लिए मजबूर होना होगा) अनिवार्य है।

बेशक प्रत्येक ऐप सर्वर (और परिनियोजन परिदृश्य) अलग-अलग होगा और यह वास्तव में प्रत्येक मामले में अनुभव से कुछ सीखा है।

+0

+1। –

+1

* "आम तौर पर फ्रेमवर्क जो अन्य कोड चलाते हैं, जैसे अनुप्रयोग सर्वर, ओएमई के चेहरे में जारी रखने का प्रयास करना" * है। मैं असहमत हूं, जब तक कि ढांचा बहुत मजबूत न हो, ओओएमई से पुनर्प्राप्त करने का प्रयास करने के परिणामस्वरूप (उदाहरण के लिए) एक catatonic सर्वर हो सकता है। वहां गया, देखा कि! –

+0

@ स्टीफन सी, मैं सोचने के लिए चिल्लाता हूं कि जेबॉस में किसी भी ओएमई पर सिस्टम.एक्सिट (1) क्या कॉल करेगा। हर बार जब उपयोगकर्ता बहुत अधिक डेटा पढ़ने के लिए थक जाता है, तो हर कोई नीचे जाता है। मैं मानता हूं कि इससे समस्याएं पैदा हो सकती हैं, लेकिन ऐप सर्वर के लिए ओएमई का सबसे अधिक संभावित कारण उपयोगकर्ता कोड बहुत अधिक कर रहा है, और जब तक वे इसे उस बिंदु पर पकड़ते हैं जहां उपयोगकर्ता कोड आवंटन अब तक पहुंच योग्य नहीं होते हैं, पूर्ण- आईएमओ के लिए रिकवरी सबसे संभावित परिणाम और कोडिंग लायक है। – Yishai

2

यह ठीक हो सकता है? संभवतः। कोई भी अच्छी तरह से लिखित जेवीएम केवल ओओएमई फेंकने जा रहा है, इसके बाद आप जो कुछ भी करने के लिए कहते हैं, उसे करने के लिए पर्याप्त स्मृति को पुनः प्राप्त करने के लिए यह सब कुछ करने की कोशिश की गई है। एक बहुत अच्छा मौका है कि इसका मतलब है कि आप ठीक नहीं हो सकते हैं। लेकिन ...

यह कई चीजों पर निर्भर करता है। उदाहरण के लिए यदि कचरा कलेक्टर प्रतिलिपि कलेक्टर नहीं है, तो "स्मृति से बाहर" स्थिति वास्तव में "आवंटित करने के लिए पर्याप्त पर्याप्त नहीं है"। ढेर को अनदेखा करने के बहुत से कार्य में बाद के जीसी दौर में वस्तुओं को साफ किया जा सकता है जो आपके उद्देश्यों के लिए पर्याप्त खुले भाग छोड़ देते हैं। उस स्थिति में आप पुनरारंभ करने में सक्षम हो सकते हैं। परिणामस्वरूप कम से कम एक बार फिर से प्रयास करना संभव है। लेकिन ...

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

3

मैं कहूंगा कि यह आउटलऑमरी एरर के कारण आंशिक रूप से निर्भर करता है। यदि जेवीएम वास्तव में स्मृति पर कम चल रहा है, तो इसे पुनरारंभ करना एक अच्छा विचार हो सकता है, और यदि संभव हो तो अधिक मेमोरी के साथ (या एक अधिक कुशल ऐप)। हालांकि, मैंने ओओएमई की उचित मात्रा देखी है जो 2 जीबी सरणी आवंटित करने के कारण हुई थी। उस स्थिति में, यदि यह जे 2 ईई वेब ऐप की तरह कुछ है, तो त्रुटि के प्रभाव उस विशेष ऐप पर बाध्य होना चाहिए, और एक जेवीएम-वाईड रीस्टार्ट कोई अच्छा नहीं करेगा।