2014-10-08 2 views
11

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

JVM में स्मृति स्थितियों से भरोसेमंद तरीके से पता लगाने का सबसे अच्छा तरीका क्या है?

  • सिद्धांत रूप में, -XX: OnOutOfMemoryError विकल्प होनहार लग रहा है, लेकिन यह इस बग के कारण प्रभावी रूप से व्यर्थ है: https://bugs.openjdk.java.net/browse/JDK-8027434

  • एक OutOfMemoryError पकड़ने वास्तव में अच्छी तरह से ज्ञात कारणों के लिए एक अच्छा विकल्प नहीं है (उदाहरण के लिए आप कभी नहीं जानते कि यह कहां होता है), हालांकि यह कई मामलों में काम करता है।

  • जो मामले रहते हैं वे हैं जहां जेवीएम फ्रीज करता है और आउटऑफमेमरी एरर नहीं फेंकता है। मुझे अभी भी यकीन है कि स्मृति इस समस्या का कारण है।

क्या कोई विकल्प या कामकाज है? कचरा संग्रहण सेटिंग्स जेवीएम को फ्रीज करने के बजाय खुद को समाप्त करने के लिए?

संपादित करें: मैं फोर्किंग और फोर्क किए गए जेवीएम दोनों के पूर्ण नियंत्रण में हूं और साथ ही साथ कोड को निष्पादित किया जा रहा है, दोनों लिनक्स पर चल रहे हैं, और यदि यह मदद करता है तो ओएस विशिष्ट उपयोगिताओं का उपयोग करना ठीक है।

+2

ऐसा लगता है कि आप वास्तव में रुचि रखते हैं कि यह पता लगा रहा है कि * एक और प्रक्रिया * में बाहर की स्मृति कब हुई है; एक महत्वपूर्ण बिंदु जिसे आपके प्रश्न के शीर्षक से भी संकेत नहीं दिया गया है। – supercat

+0

धन्यवाद। मैंने इस पोस्ट में और अधिक स्पष्ट करने की कोशिश की, लेकिन मैंने अभी तक शीर्षक नहीं बदला है, क्योंकि सभी वैकल्पिक खिताब मैं आने में सक्षम था, भ्रामक थे। विशेष रूप से मुझे कोई फर्क नहीं पड़ता कि क्या हम JVM को कॉल करने से JVM के अंदर से जानकारी प्राप्त करते हैं, इसे अपने विशिष्ट व्यवहार के साथ JVM के रूप में देखकर, या इसे केवल प्रक्रिया के रूप में देखकर। –

+2

यदि आप अपना शीर्षक सुधार नहीं पाते हैं, तो बहुत से लोग जो उत्तर देने में सक्षम हो सकते हैं, वे आपकी पोस्ट को खोलने की संभावना नहीं रखते हैं। शायद "जावा वीएम प्रक्रिया मेमोरी से बाहर होने पर अलार्म ट्रिगर करना" बेहतर शीर्षक होगा? – supercat

उत्तर

1

पिछले कुछ समय से इस के साथ प्रयोग करने के बाद, यह समाधान है कि हम के लिए काम किया है:

  1. पैदा की JVM में, तुरंत एक OutOfMemoryError और बाहर निकलने को पकड़ने, नियंत्रक JVM पर एक निकास के कोड के साथ स्मृति हालत से बाहर संकेत ।
  2. उत्पन्न जेवीएम में, समय-समय पर वर्तमान Runtime की खपत वाली स्मृति की मात्रा की जांच करें। जब उपयोग की गई स्मृति की मात्रा महत्वपूर्ण के करीब होती है, तो एक ध्वज फ़ाइल बनाएं जो नियंत्रक JVM को स्मृति स्थिति से बाहर सिग्नल करे। अगर हम इस स्थिति से ठीक हो जाते हैं और सामान्य रूप से बाहर निकलते हैं, तो बाहर निकलने से पहले उस फ़ाइल को हटा दें।
  3. नियंत्रण के बाद जेवीएम फोर्क किए गए जेवीएम में शामिल हो जाता है, यह चरण (1) में उत्पन्न निकास कोड और चरण (2) में उत्पन्न ध्वज फ़ाइल की जांच करता है। इसके अलावा, यह जांचता है कि फ़ाइल hs_err_pidXXX.log मौजूद है या नहीं, "मेमोरी त्रुटि से बाहर" पंक्ति है। (यह फ़ाइल जावा द्वारा उत्पन्न होने पर उत्पन्न होती है।)

केवल उन सभी चेक को लागू करने के बाद हम उन सभी मामलों को संभालने में सक्षम थे जहां फोर्क किए गए JVM स्मृति से बाहर हो गए थे। हम मानते हैं कि तब से, हमने ऐसा कोई मामला नहीं छोड़ा है जहां यह हुआ था।

जाल ध्वज -XX:OnOutOfMemoryError का उपयोग फोर्क समस्या के कारण नहीं किया गया था, और -XX:+HeapDumpOnOutOfMemoryError का उपयोग नहीं किया गया था क्योंकि एक हीप डंप की आवश्यकता से अधिक है।

समाधान निश्चित रूप से कभी भी लिखे गए कोड का सबसे सुंदर टुकड़ा नहीं है, लेकिन हमारे लिए काम किया है।

0

यदि आपके पास एप्लिकेशन और कॉन्फ़िगरेशन दोनों पर नियंत्रण है, तो सबसे अच्छा समाधान आउटऑफमेमरी एरर फेंकने और इसे ठीक करने के लिए अंतर्निहित कारणों को ढूंढना होगा, या तो त्रुटि को पकड़कर या तो लक्षणों को छिपाने की कोशिश करने के बजाय JVMs को पुनरारंभ करना।

जो आप वर्णन करते हैं, उससे निश्चित रूप से लगता है कि या तो जेवीएम पर चल रहा एप्लिकेशन स्मृति को लीक कर रहा है, केवल अंडर-प्रावधान संसाधन (आपके मामले में स्मृति) का उपयोग कर चल रहा है या कभी-कभी लेन-देन को संसाधित करता है जिसमें ढेर के असामान्य रूप से बड़े हिस्से की आवश्यकता होती है। उन मामलों के लिए समाधान अलग होंगे:

  1. स्मृति रिसाव के मामले में, अंतर्निहित कारण ढूंढें और इंजीनियरों को इसे ठीक करें। इसके लिए टूल्स में हेप डंप विश्लेषक, प्रोफाइलर या रिसाव डिटेक्टर
  2. अंडर-प्रावधान संसाधनों के मामले में आपको एप्लिकेशन मेमोरी खपत की निगरानी करने की आवश्यकता है, उदाहरण के लिए कचरा संग्रहण लॉग के माध्यम से और आप जो भी सामना करते हैं उसके आधार पर विभिन्न मेमोरी पूल के आकार समायोजित करें ।
  3. उपयोगकर्ता लेनदेन के दौरान वृद्धि आवंटन के मामले में, आपको कुछ उपयोगकर्ता इनपुट को अक्षम करने या छोटे बैचों में डेटा को लोड करने और संसाधित करने के माध्यम से कोड को ठीक करने और इंजीनियरों को ठीक करने के कारण कोड का पता लगाने की आवश्यकता होती है। या तो प्रक्रियाओं से थ्रेड डंप या हीप डंप आपको समाधान की दिशा में मार्गदर्शन कर सकते हैं।
+0

प्रश्न से मुझे लगता है कि वहां कोई भी कारण नहीं था OutOfMemory, बस मनमाना उपयोगकर्ता कोड चलाया जा रहा है। मुझे नहीं लगता कि वह पूछ रहा है कि उपयोगकर्ता के कोड को कैसे ठीक किया जाए –

+0

यह सही है। लोग वर्कफ़्लो सबमिट करते हैं (इसे विज़ुअल प्रोग्रामिंग के रूप में सोचें) हमारे लिए। हम उन्हें फोर्क किए गए जेवीएम में चलाते हैं। यदि ऐसा कोई वर्कफ़्लो 8 जीबी मशीन पर ऐसा करने के दौरान 16 जीबी डेटा फ़ाइल पर मैट्रिक्स ऑपरेशन करता है, तो यह काम नहीं कर सकता है। कॉलर को इसे ठीक करना है, लेकिन हमें उन्हें बताने की जरूरत है कि स्मृति समस्या है, न कि हमारे अंत में एक JVM बग या अन्य बग। –

+0

इस मामले में, प्लमब्र (https://plumbr.eu) बस ऐसा करेगा - उदाहरण के लिए मेमोरी रिसाव के मामले में आपको सटीक मूल कारण मिलेगा जिसे आप इंजीनियरिंग में भेज सकते हैं जो उस पर आधारित है जो तुरंत अंतर्निहित में ज़ूम कर सकता है प्लंबरब्र की घटना रिपोर्ट के रूप में समस्या इस मुद्दे के कारण स्रोत कोड में सटीक रेखा को संदर्भित करती है। – Ivo

1

एकमात्र असली विकल्प (दुर्भाग्य से) वीएम को जल्द से जल्द समाप्त करने के लिए है।

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

java .... -XX:+HeapDumpOnOutOfMemoryError "-XX:OnOutOfMemeoryError=kill %p" 
+0

द -XX: + HeapDumpOnOutOfMemoryError वास्तव में एक विकल्प है जिसे हमने अभी तक कोशिश नहीं की है। अभी तक, ऐसा लगता है कि यह विश्वसनीय रूप से भी नहीं बनाया गया है। WRT the -XX: OnOutOfMemoryError: यह काम करता है, लेकिन केवल अगर ओएस की कुल स्मृति का ~ 50% अभी भी उपलब्ध है, तो इस मामले में मैं इसे केवल इस उद्देश्य के लिए आरक्षित करने के बजाय JVM को दे दूंगा :-) –

+0

@ सिमोन फिशर आईएमएचओ जेआरई रनटाइम # exec() के लिए vfork पर स्विच किया गया, मुझे यकीन नहीं है कि इसमें OnOutOfMemory भी शामिल है। लेकिन निश्चित रूप से यह सही है कि यह अंतरिक्ष बाधित स्थितियों में कमांड को निष्पादित करने में सक्षम नहीं हो सकता है। मैं क्रैश रिपोर्टर सर्वर और ओएस क्रैश रिपोर्टिंग के बारे में निश्चित नहीं हूं अगर वे विकल्प हैं। आखिरकार आपको वांछित प्रक्रिया की जांच करनी होगी। – eckes

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