जावा में मेमोरी रिसाव / कचरा-संग्रह के मुद्दे को ट्रैक करना


79

यह एक समस्या है जिसे मैं अभी कुछ महीनों के लिए ट्रैक करने की कोशिश कर रहा हूं। मेरे पास एक जावा ऐप है जो xml को प्रोसेस करता है और एक डेटाबेस में रिजल्ट को स्टोर करता है। आंतरायिक संसाधन समस्याएं हैं जिन्हें नीचे ट्रैक करना बहुत मुश्किल है।

पृष्ठभूमि: उत्पादन बॉक्स पर (जहां समस्या सबसे अधिक ध्यान देने योग्य है), मेरे पास बॉक्स तक विशेष रूप से अच्छी पहुंच नहीं है, और Jprofiler चलाने में असमर्थ है। वह बॉक्स 64 बिट क्वाड-कोर, 8 जीबी मशीन पर चलने वाला सेंटोस 5.2, टॉमकैट 6 और जावा 1.6.0.11 है। इसकी शुरुआत इन जावा-ऑप्स से होती है

JAVA_OPTS="-server -Xmx5g -Xms4g -Xss256k -XX:MaxPermSize=256m -XX:+PrintGCDetails -
XX:+PrintGCTimeStamps -XX:+UseConcMarkSweepGC -XX:+PrintTenuringDistribution -XX:+UseParNewGC"

प्रौद्योगिकी स्टैक निम्नलिखित है:

  • सेंटोस 64-बिट 5.2
  • जावा 6u11
  • तोमक ६
  • स्प्रिंग / वेबएमवीसी 2.5
  • सीतनिद्रा में होना ३
  • क्वार्ट्ज 1.6.1
  • DBCP 1.2.1
  • मायिकल 5.0.45
  • Ehcache 1.5.0
  • (और निश्चित रूप से अन्य निर्भरताओं के एक मेजबान, विशेष रूप से जकार्ता-कॉमन्स पुस्तकालयों)

समस्या को पुन: उत्पन्न करने के लिए निकटतम मैं एक 32-बिट मशीन हो सकती है जिसमें कम मेमोरी आवश्यकताएं हैं। कि मेरा नियंत्रण नहीं है। मैंने इसे JProfiler के साथ मौत के घाट उतार दिया है और कई प्रदर्शन समस्याओं (सिंक्रनाइज़ेशन समस्याओं, precompiling / कैशिंग xpath क्वेरीज़, थ्रेडपूल को कम करने, और अनावश्यक हाइबरनेट को हटाने, और प्रसंस्करण के दौरान अत्यधिक "कैश-वार्मिंग") को निर्धारित किया है।

प्रत्येक मामले में, प्रोफाइलर ने एक कारण या किसी अन्य के लिए भारी मात्रा में संसाधनों को लेने के रूप में दिखाया, और ये कि अब एक बार परिवर्तन होने के बाद प्राथमिक संसाधन हॉग नहीं थे।

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

समस्या कचरा संग्रहण प्रतीत होती है। हम समवर्तीमार्टस्वीप का उपयोग कर रहे हैं (जैसा कि ऊपर उल्लेख किया गया है) कलेक्टर क्योंकि मूल एसटीडब्ल्यू कलेक्टर जेडीबीसी समयबाह्य कर रहे थे और तेजी से धीमी हो गई थी। लॉग दिखाते हैं कि जैसे-जैसे मेमोरी का उपयोग बढ़ता है, वैसे-वैसे सीएमएस विफलताओं को फेंकना शुरू होता है, और मूल स्टॉप-द-वर्ल्ड कलेक्टर को वापस मारता है, जो तब ठीक से इकट्ठा नहीं होता है।

हालाँकि, jprofiler के साथ चल रहा है, "Run GC" बटन एक बढ़ते पदचिह्न दिखाने के बजाय स्मृति को अच्छी तरह से साफ करने के लिए लगता है, लेकिन चूंकि मैं जिप्टाइलर को सीधे उत्पादन बॉक्स से नहीं जोड़ सकता हूं, और साबित हॉटस्पॉट्स को हल करने के लिए काम नहीं कर रहा हूं। ट्यूनिंग कचरा संग्रह अंधा के जादू के साथ छोड़ दिया।

मैंने क्या कोशिश की है:

  • प्रोफाइलिंग और फिक्सिंग हॉटस्पॉट्स।
  • एसटीडब्ल्यू, समानांतर और सीएमएस कचरा संग्राहकों का उपयोग करना।
  • 1 / 2,2 / 4,4 / 5,6 / 6 वेतन वृद्धि पर न्यूनतम / अधिकतम आकार के साथ चल रहा है।
  • 256M वेतन वृद्धि में permgen स्थान के साथ चल रहा है 1Gb तक।
  • उपरोक्त के कई संयोजन।
  • मैंने JVM [ट्यूनिंग संदर्भ] (http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html) से भी सलाह ली है, लेकिन वास्तव में इस व्यवहार या _which_ ट्यूनिंग के किसी भी उदाहरण की व्याख्या करते हुए कुछ भी नहीं पा सकते हैं। इस तरह की स्थिति में उपयोग करने के लिए पैरामीटर।
  • मैंने ऑफलाइन मोड में जिप्सीलर की भी कोशिश की है, जोन्कोसोल, विजुअल्म से जुड़कर, लेकिन मुझे ऐसा कुछ भी नहीं मिल रहा है जो मेरे जीसी लॉग डेटा को इंटरप्रेट करे।

दुर्भाग्य से, समस्या भी छिटपुट रूप से पॉप हो जाती है, यह अप्रत्याशित लगता है, यह किसी भी समस्या के बिना दिनों या एक सप्ताह तक चल सकता है, या यह एक दिन में 40 बार विफल हो सकता है, और केवल एक चीज जिसे मैं लगातार पकड़ सकता हूं। वह कचरा संग्रहण कार्य कर रहा है।

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

किसी भी और सभी जानकारी के लिए धन्यवाद जो आप प्रदान कर सकते हैं।

EDIT
एमिल एच:
1) हां, मेरा विकास क्लस्टर उत्पादन डेटा का एक दर्पण है, मीडिया सर्वर के नीचे। प्राथमिक अंतर 32/64 बिट और उपलब्ध RAM की मात्रा है, जिसे मैं बहुत आसानी से दोहरा नहीं सकता, लेकिन कोड और क्वेरीज़ और सेटिंग्स समान हैं।

2) कुछ विरासत कोड है जो कि जैक्सबी पर निर्भर है, लेकिन शेड्यूलिंग संघर्षों से बचने की कोशिश करने के लिए नौकरियों को पुन: व्यवस्थित करने में, मेरे पास उस निष्पादन को आम तौर पर समाप्त हो जाता है क्योंकि यह दिन में एक बार चलता है। प्राथमिक पार्सर XPath प्रश्नों का उपयोग करता है जो java.xml.xpath पैकेज के लिए कॉल करते हैं। यह कुछ हॉटस्पॉट्स का स्रोत था, एक के लिए प्रश्नों को पूर्व-संकलित नहीं किया जा रहा था, और उनमें से दो संदर्भ हार्डकोडिंग स्ट्रिंग्स में थे। मैंने थ्रेडसेफ़ कैश (हैशमैप) बनाया और अंतिम स्थैतिक स्ट्रिंग्स होने के लिए xpath प्रश्नों के संदर्भों को फैक्टर किया, जिससे संसाधन की खपत काफी कम हो गई। क्वेरी अभी भी प्रोसेसिंग का एक बड़ा हिस्सा है, लेकिन ऐसा इसलिए होना चाहिए क्योंकि यह एप्लिकेशन की मुख्य जिम्मेदारी है।

3) एक अतिरिक्त नोट, अन्य प्राथमिक उपभोक्ता JAI से इमेज ऑपरेशंस (फीड से इमेज को रीप्रोसेस करते हुए) है। मैं जावा के ग्राफिक पुस्तकालयों से अपरिचित हूं, लेकिन मैंने जो पाया है, वे विशेष रूप से लीक नहीं हैं।

(अब तक के जवाब के लिए धन्यवाद, दोस्तों!)

अद्यतन:
मैं VisualVM के साथ उत्पादन उदाहरण से कनेक्ट करने में सक्षम था, लेकिन इसने GC विज़ुअलाइज़ेशन / रन-GC विकल्प को अक्षम कर दिया था (हालांकि मैं इसे स्थानीय रूप से देख सकता था)। दिलचस्प बात यह है: VM का ढेर आवंटन JAVA_OPTS का पालन कर रहा है, और वास्तविक आवंटित ढेर 1-1.5 गिग्स पर आराम से बैठा है, और doesn't लीक हो रहा है, लेकिन बॉक्स स्तर की निगरानी अभी भी एक लीक पैटर्न दिखाती है, लेकिन यह है वीएम निगरानी में परिलक्षित नहीं। इस बॉक्स में और कुछ नहीं चल रहा है, इसलिए मैं स्तब्ध हूं।


क्या आप परीक्षण के लिए realworld डेटा और एक realworld डेटाबेस का उपयोग करते हैं? अधिमानतः उत्पादन डेटा की एक प्रति?
एमिल एच।

4
+1 - यह मेरे द्वारा पढ़े गए सबसे अच्छे प्रश्नों में से एक है। मेरी इच्छा है कि मेरे पास मदद के संदर्भ में और अधिक पेशकश हो। मैं यह देखने के लिए वापस आऊंगा कि क्या किसी के पास कहने के लिए कुछ स्मार्ट है।
duffymo

इसके अलावा, आप किस XML- पार्सर का उपयोग कर रहे हैं?
एमिल एच।

क्या आपको बाइटबफर्स ​​की संख्या आवंटित की गई थी और उन्हें कौन आवंटित करता है?
शॉन मैकॉफिल

इस उत्तर की जाँच करें: stackoverflow.com/a/35610063 , इसमें जावा देशी मेमोरी लीक के बारे में विवरण है।
लारी होटारी

जवाबों:


92

खैर, आखिरकार मुझे वह मुद्दा मिल गया जो यह कारण था, और मैं किसी अन्य व्यक्ति के पास इन मुद्दों के बारे में विस्तार से उत्तर दे रहा हूं।

जब मैंने इस प्रक्रिया को निभा रहा था, तो मैंने जंप करने की कोशिश की, लेकिन इससे आमतौर पर jvm आगे लटक गया और मुझे इसे लागू करना पड़ा। यह ढेर डंप के परिणामस्वरूप था जो बहुत सारे डेटा को गायब कर रहा था, या कम से कम उनके बीच के संदर्भों को गायब कर रहा था। विश्लेषण के लिए, मैंने झट की कोशिश की, जो बहुत सारे डेटा प्रस्तुत करता है, लेकिन इसकी व्याख्या करने के तरीके में बहुत अधिक नहीं है। दूसरे, मैंने ग्रहण-आधारित स्मृति विश्लेषण टूल ( http://www.eclipse.org/mat/ ) की कोशिश की , जिससे पता चला कि ढेर ज्यादातर टॉमकैट से संबंधित कक्षाएं थीं।

मुद्दा यह था कि जम्प आवेदन की वास्तविक स्थिति की रिपोर्ट नहीं कर रहा था, और केवल शटडाउन पर कक्षाओं को पकड़ रहा था, जो ज्यादातर टॉमकैट कक्षाएं थीं।

मैंने कुछ और समय की कोशिश की, और देखा कि मॉडल ऑब्जेक्ट्स की कुछ बहुत अधिक मात्राएं थीं (वास्तव में डेटाबेस में सार्वजनिक रूप से चिह्नित किए गए 2-3x अधिक थे)।

इसका उपयोग करके मैंने धीमी क्वेरी लॉग और कुछ असंबंधित प्रदर्शन समस्याओं का विश्लेषण किया। मैंने अतिरिक्त-आलसी लोड करने की कोशिश की ( http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html ), साथ ही प्रत्यक्ष jdcc प्रश्नों के साथ कुछ हाइबरनेट संचालन की जगह (ज्यादातर यह कहाँ है) बड़े संग्रह पर लोडिंग और संचालन के साथ काम कर रहा था - jdbc रिप्लेसमेंट ने सीधे जॉइन टेबल पर काम किया), और कुछ अन्य अयोग्य प्रश्नों को प्रतिस्थापित किया जो कि mysql लॉगिंग थे।

इन कदमों ने फ्रंटएंड प्रदर्शन के टुकड़ों में सुधार किया, लेकिन फिर भी रिसाव के मुद्दे को संबोधित नहीं किया, ऐप अभी भी अस्थिर था और अप्रत्याशित रूप से कार्य कर रहा था।

अंत में, मुझे विकल्प मिला: -XX: + HeapDumpOnOutOfMemoryError। यह अंततः एक बहुत बड़ी (~ 6.5GB) hprof फ़ाइल का उत्पादन करता है जिसने एप्लिकेशन की स्थिति को सटीक रूप से दिखाया। विडंबना यह है कि फ़ाइल इतनी बड़ी थी कि jhat इसे एलाइज नहीं कर सकता था, यहां तक ​​कि 16gb के साथ बॉक्स पर भी। सौभाग्य से, MAT कुछ अच्छे दिखने वाले रेखांकन का उत्पादन करने में सक्षम था और कुछ बेहतर आंकड़े दिखाए।

इस बार जो अटक गया वह एक एकल क्वार्ट्ज धागा था जो 6GB के ढेर में से 4.5GB ले रहा था, और इसका अधिकांश हिस्सा एक हाइबरनेट स्टेटफुलपर्सिस्टेंससोनेटेक्स्ट ( https://www.hibernate.org/hib_bocs/v3/api/org/hibernate था /engine/StatefulPersistenceContext.html )। इस वर्ग का उपयोग आंतरिक रूप से हाइबरनेट द्वारा किया जाता है क्योंकि इसका प्राथमिक कैश (मैंने EHCache द्वारा समर्थित द्वितीय-स्तर और क्वेरी-कैश को अक्षम कर दिया था)।

इस वर्ग का उपयोग हाइबरनेट की अधिकांश विशेषताओं को सक्षम करने के लिए किया जाता है, इसलिए इसे सीधे अक्षम नहीं किया जा सकता है (आप इसके चारों ओर सीधे काम कर सकते हैं, लेकिन वसंत स्टेटलेस सत्र का समर्थन नहीं करता है), और मुझे बहुत आश्चर्य होगा अगर यह ऐसा था एक परिपक्व उत्पाद में प्रमुख मेमोरी रिसाव। तो अब क्यों लीक हो रहा था?

ठीक है, यह चीजों का एक संयोजन था: क्वार्ट्ज थ्रेड पूल तात्कालिक चीजें थ्रेडलोकल होने के साथ, स्प्रिंग एक सत्र कारखाने में इंजेक्शन लगा रहा था, जो कि क्वार्ट्ज थ्रेड्स जीवन चक्र की शुरुआत में एक सत्र का निर्माण कर रहा था, जिसे तब चलाने के लिए दुरुपयोग किया जा रहा था। विभिन्न क्वार्ट्ज नौकरियां जो हाइबरनेट सत्र का उपयोग करती थीं। हाइबरनेट तब सत्र में कैशिंग कर रहा था, जो इसका अपेक्षित व्यवहार है।

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

इसलिए सत्र को कभी बंद नहीं किया जा रहा था, हाइबरनेट कैश ऑब्जेक्ट्स के संदर्भों को बनाए रख रहा था, इसलिए वे कभी भी कचरा एकत्र नहीं कर रहे थे, इसलिए हर बार एक नई नौकरी चलाने से यह बस कैश को थ्रेड तक भरता रहेगा, इसलिए वहां भी नहीं था विभिन्न नौकरियों के बीच किसी भी साझा। इसके अलावा चूंकि यह एक लेखन-गहन काम है (बहुत कम पढ़ने वाला), कैश ज्यादातर बर्बाद हो गया था, इसलिए ऑब्जेक्ट बनाए जाते रहे।

समाधान: एक डाओ विधि बनाएं जो स्पष्ट रूप से session.flush () और session.clear () को बुलाती है, और प्रत्येक कार्य की शुरुआत में उस पद्धति को लागू करती है।

ऐप कुछ दिनों से बिना किसी निगरानी के, स्मृति त्रुटियों या पुनरारंभ के साथ चल रहा है।

इस पर हर किसी की मदद के लिए धन्यवाद, यह ट्रैक करने के लिए एक बहुत मुश्किल बग था, जैसा कि सब कुछ ठीक वैसा ही कर रहा था जैसा कि यह माना जाता था, लेकिन अंत में एक 3 लाइन विधि सभी समस्याओं को ठीक करने में कामयाब रही।


13
आपकी डिबगिंग प्रक्रिया का अच्छा तरीका है और संकल्प को पूरा करने और पोस्ट करने के लिए धन्यवाद।
बोरिस टेरिक

1
अच्छी व्याख्या के लिए धन्यवाद। मेरे पास बैच रीड (SELECT) परिदृश्य में एक समान समस्या थी, जिसके परिणामस्वरूप StatefulPersistenceContext इतना बड़ा हो गया। मैं em.clear () या em.flush () नहीं चला सका क्योंकि मेरी मुख्य लूपिंग विधि थी @Transactional(propagation = Propagation.NOT_SUPPORTED)। इसे बदलने के लिए Propagation.REQUIREDऔर em.flush / em.clear () को कॉल करके हल किया गया था ।
मोहसिन

3
एक बात जो मुझे समझ में नहीं आती है: यदि सत्र को कभी भी फ्लश नहीं किया गया था, तो इसका मतलब है कि कोई वास्तविक डेटा DB में सहेजा नहीं गया था। क्या इस डेटा को आपके आवेदन में कुछ और जगह नहीं मिली है, ताकि आप देख सकें कि यह गायब है?
23

1
StatefulPersistenceContext के लिए प्रदान किया गया लिंक टूट गया है। क्या यह अब docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/engine/… है?
विक्टर स्टैफुसा

1
लियाम, एक टन धन्यवाद। मेरे पास एक ही मुद्दा है और MAT स्टेटसपर्सेंटेंटसेंटटेक्स्ट को हाइबरनेट करने का इशारा कर रहा है। मुझे लगता है कि आपके लेख को पढ़कर मुझे पर्याप्त संकेत मिले। ऐसी अद्भुत जानकारी के लिए धन्यवाद।
Reddymails

4

आप JMX सक्षम के साथ उत्पादन बॉक्स चला सकते हैं?

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=<port>
...

निगरानी और प्रबंधन JMX का उपयोग करना

और फिर JConsole, VisualVM के साथ संलग्न करें ?

क्या जम्प के साथ ढेर डंप करना ठीक है ?

यदि हाँ, तो आप JProfiler (आप पहले से ही), jhat , VisualVM, ग्रहण MAT के साथ लीक के लिए ढेर डंप का विश्लेषण कर सकते हैं । इसके अलावा ढेर ढेर की तुलना करें जो लीक / पैटर्न खोजने में मदद कर सकते हैं।

और जैसा कि आपने जकार्ता-कॉमन्स का उल्लेख किया है। क्लास लोडर पर होल्डिंग से संबंधित जकार्ता-कॉमन्स-लॉगिंग का उपयोग करते समय एक समस्या है। उस चेक पर एक अच्छी रीड के लिए

स्मृति रिसाव शिकारी के जीवन में एक दिन ( release(Classloader))


1) मैंने आज वास्तव में विज़ुअल्म और कुछ अन्य उपकरणों की कोशिश की है, लेकिन बंदरगाहों को ठीक से खोलने की आवश्यकता है। 2) मैंने अपनी पिछली नौकरी में सी-लॉगिंग मुद्दे को देखा, वास्तव में और इस समस्या ने मुझे इसकी याद दिला दी। एक कंपनी-व्यापी सेवा नियमित रूप से दुर्घटनाग्रस्त हो रही थी और इसे कॉमन्स में एक ज्ञात रिसाव पर ट्रैक किया गया था, मेरा मानना ​​है कि यह कुछ ऐसा ही था जैसा आपने लिंक किया था। मैंने अधिकांश लॉगिंग को log4j के रूप में रखने की कोशिश की है, लेकिन मेरे पास आश्रित परियोजनाओं पर ज्यादा विकल्प नहीं हैं जिनके लिए कॉमन्स पैकेज की आवश्यकता है। हमारे पास सिंपलफैकेड का उपयोग करने वाली कुछ कक्षाएं भी हैं, मैं अब देख रहा हूं कि क्या मैं चीजों को थोड़ा अधिक सुसंगत बना सकता हूं।
लियाम

4

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

यदि यह एक पर्मेन रिसाव हो जाता है तो डिबगिंग मुश्किल हो जाता है क्योंकि पर्मगेन विश्लेषण के लिए टूलिंग में ढेर की तुलना में कमी होती है। आपका सबसे अच्छा दांव सर्वर पर एक छोटी स्क्रिप्ट शुरू करना है जो बार-बार (हर घंटे?) आह्वान करता है:

jmap -permstat <pid> > somefile<timestamp>.txt

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

एक बार जब आप कुछ वर्गों को लोड किए जाने के रूप में पहचान लेते हैं और लोड नहीं किए जाते हैं, तो आप मानसिक रूप से यह पता लगा सकते हैं कि ये कहां उत्पन्न हो सकते हैं, अन्यथा आप जैम-डंप के साथ उत्पन्न डंप का विश्लेषण करने के लिए झट का उपयोग कर सकते हैं। मैं रखता हूँ कि भविष्य के अद्यतन के लिए आपको जानकारी चाहिए।


अच्छा सुझाव। मैं कोशिश करूंगा कि आज दोपहर
लियाम

jmap ने मदद नहीं की, लेकिन करीब था। स्पष्टीकरण के लिए पूर्ण उत्तर देखें।
liam

2

मैं सीधे बाइटबफ़र आवंटित करूँगा।

जावदोक से।

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

शायद टॉमकैट कोड इसका उपयोग I / O के लिए करता है; एक अलग कनेक्टर का उपयोग करने के लिए टॉमकैट कॉन्फ़िगर करें।

असफल होना कि आपके पास एक धागा हो सकता है जो समय-समय पर System.gc () निष्पादित करता है। "-XX: + ExplicitGCInvokesConcurrent" कोशिश करने के लिए एक दिलचस्प विकल्प हो सकता है।


1) जब आप कनेक्टर कहते हैं, तो क्या आप DB कनेक्टर, या एक अलग IO बाउंड क्लास का जिक्र कर रहे हैं? व्यक्तिगत रूप से मैं बल्कि नए कनेक्शन पूल को शुरू करने के प्रयास से नहीं गुजरूंगा, भले ही c3p0 एक करीबी मैच हो, लेकिन बीमार ने इसे एक संभावना के रूप में रखा। 2) मैं स्पष्ट जीसी ध्वज के पार नहीं आया हूं, लेकिन मैं निश्चित रूप से इस पर विचार करूंगा। यह थोड़ा हैकिश लगता है, हालांकि, और इस आकार के एक विरासत कोडबेस के साथ, मैं उस दृष्टिकोण से दूर जाने की कोशिश कर रहा हूं। (पूर्व: कुछ महीने पहले मुझे कई स्पॉट्स को ट्रैक करना था जो साइड इफेक्ट्स के रूप में थ्रेडिंग कर रहे थे। थ्रेड्स अब समेकित हैं)।
लियाम

1) जब से मैंने टॉमकैट को कॉन्फ़िगर किया है, कुछ समय हो गया है। इसमें एक अवधारणा होती है जिसे कनेक्टर कहा जाता है ताकि आप इसे अपाचे httpd के अनुरोधों को सुनने या HTTP के लिए सीधे सुनने के लिए कॉन्फ़िगर कर सकें। कुछ बिंदु पर एक NIO http कनेक्टर और एक मूल HTTP कनेक्टर था। आप देख सकते हैं कि NIO HTTP कनेक्टर के लिए कौन से कॉन्फ़िगरेशन विकल्प उपलब्ध हैं या देखें कि क्या एकमात्र मूल कनेक्टर उपलब्ध है। 2) आपको केवल उस थ्रेड की आवश्यकता है जो समय-समय पर System.gc () को कॉल करता है या आप टाइम थ्रेड का पुन: उपयोग कर सकते हैं। हां, यह पूरी तरह से हैकिंग है।
शॉन मैकॉफिल

मूल स्मृति लीक डीबग करने के लिए stackoverflow.com/questions/26041117/… देखें ।
लारी होटरी

1

कोई JAXB? मुझे लगता है कि JAXB एक पर्म स्पेस सामान है।

इसके अलावा, मुझे लगता है कि विजुअल्क , अब जेडीके 6 के साथ भेज दिया गया है, यह देखने का एक शानदार तरीका है कि स्मृति में क्या हो रहा है। यह सुंदर रूप से जीसी के क्षणिक, सामान्य और परमिट स्थानों और क्षणिक व्यवहार को दर्शाता है। आपको बस प्रक्रिया की पीआईडी ​​चाहिए। हो सकता है कि जब आप JProfile पर काम करते हैं तो यह मदद करेगा।

और स्प्रिंग ट्रेसिंग / लॉगिंग पहलुओं के बारे में क्या? हो सकता है कि आप एक साधारण पहलू लिख सकते हैं, इसे घोषित रूप से लागू कर सकते हैं, और उस तरह से एक गरीब आदमी का प्रोफाइलर कर सकते हैं।


1) मैं एक दूरस्थ बंदरगाह को खोलने की कोशिश करने के लिए SA के साथ काम कर रहा हूं, और मैं देशी जावा / jmx आधारित टूल (मैं कुछ की कोशिश की है, जिसमें jprofiler शामिल है - महान उपकरण! - लेकिन यह बहुत मुश्किल हो रहा था। उचित सिस्टम स्तर के लिबास)। 2) मैं बस वसंत से भी पहलू-उन्मुख कुछ से बहुत सावधान हूं। मेरे अनुभव में, यहां तक ​​कि उस पर निर्भरता होने से चीजें अधिक भ्रामक और कॉन्फ़िगर करने में कठिन हो जाती हैं। बीमार इसे ध्यान में रखें अगर कुछ और काम नहीं करता है, हालांकि।
लियाम

1

"दुर्भाग्य से, समस्या भी छिटपुट रूप से पॉप होती है, यह अप्रत्याशित प्रतीत होता है, यह किसी भी समस्या के बिना दिनों या एक सप्ताह तक चल सकता है, या यह एक दिन में 40 बार विफल हो सकता है, और केवल एक चीज जिसे मैं लगातार पकड़ सकता हूं। वह कचरा संग्रहण कार्य कर रहा है। "

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

यदि XML आयात द्वारा ऐसा होता है, तो आपको डेटा के साथ 40 क्रैश दिन के XML डेटा की तुलना करनी चाहिए, जो कि शून्य क्रैश दिवस पर आयात किया जाता है। हो सकता है कि यह किसी प्रकार की तार्किक समस्या हो, जिसे आप अपने कोड के अंदर नहीं पाते हैं।


1

मैं एक ही समस्या थी, कुछ मतभेदों के साथ ..

मेरी तकनीक निम्नलिखित है:

अनाज 2.2.4

tomcat7

क्वार्ट्ज-प्लगइन 1.0

मैं अपने आवेदन पर दो डेटा स्रोत का उपयोग करता हूं। यह बग कारणों के लिए एक विशिष्टता है।

विचार करने के लिए एक और बात यह है कि क्वार्ट्ज-प्लगइन, क्वार्ट्ज थ्रेड्स में हाइबरनेट सत्र इंजेक्ट करें, जैसे @liam कहते हैं, और क्वार्ट्ज थ्रेड्स अभी भी जीवित हैं, जब तक मैं आवेदन समाप्त नहीं करता।

मेरी समस्या अनाज ओआरएम पर एक बग थी, जिस तरह से प्लगइन हैंडल सत्र और मेरे दो डेटा स्रोत।

क्वार्ट्ज प्लगइन में एक श्रोता को init और हाइबरनेट सत्रों को नष्ट करने के लिए था

public class SessionBinderJobListener extends JobListenerSupport {

    public static final String NAME = "sessionBinderListener";

    private PersistenceContextInterceptor persistenceInterceptor;

    public String getName() {
        return NAME;
    }

    public PersistenceContextInterceptor getPersistenceInterceptor() {
        return persistenceInterceptor;
    }

    public void setPersistenceInterceptor(PersistenceContextInterceptor persistenceInterceptor) {
        this.persistenceInterceptor = persistenceInterceptor;
    }

    public void jobToBeExecuted(JobExecutionContext context) {
        if (persistenceInterceptor != null) {
            persistenceInterceptor.init();
        }
    }

    public void jobWasExecuted(JobExecutionContext context, JobExecutionException exception) {
        if (persistenceInterceptor != null) {
            persistenceInterceptor.flush();
            persistenceInterceptor.destroy();
        }
    }
}

मेरे मामले में, persistenceInterceptorउदाहरण AggregatePersistenceContextInterceptor, और इसकी एक सूची थी HibernatePersistenceContextInterceptor। प्रत्येक डेटा स्रोत के लिए एक।

प्रत्येक AggregatePersistenceContextInterceptorसंशोधन किसी भी संशोधन या उपचार के बिना, हाइबरनेटपर्सिस्टेंस को पारित कर दिया जाता है।

जब हम कॉल init()करते हैं HibernatePersistenceContextInterceptorतो वह नीचे दिए गए स्थिर चर को बढ़ाता है

private static ThreadLocal<Integer> nestingCount = new ThreadLocal<Integer>();

मुझे उस स्थिर गणना का पता नहीं है। मुझे सिर्फ इतना पता है कि वह दो बार इन्क्रीमेंट कर चुका है, एक प्रति डेटासोर्स, की वजह सेAggregatePersistence लागू करने ।

यहाँ तक मैं सिनेरियो की व्याख्या करता हूँ।

समस्या अब आती है ...

जब मेरी क्वार्ट्ज नौकरी खत्म हो जाती है, तो प्लगइन श्रोता को हाइबरनेट सत्रों को फ्लश और नष्ट करने के लिए कहता है, जैसे आप स्रोत कोड में देख सकते हैं SessionBinderJobListener

फ्लश पूरी तरह से होता है, लेकिन नष्ट नहीं होता है, क्योंकि HibernatePersistence, करीब हाइबरनेट सत्र से पहले एक सत्यापन करें ... यह जांच करता हैnestingCount देखने के लिए है कि क्या मूल्य 1 से अधिक है। यदि उत्तर हाँ है, तो वह सत्र बंद नहीं करता है।

हाइबरनेट द्वारा क्या किया गया था:

if(--nestingCount.getValue() > 0)
    do nothing;
else
    close the session;

यह मेरी स्मृति रिसाव का आधार है। क्वार्ट्ज के धागे अभी भी सत्र में इस्तेमाल होने वाली सभी वस्तुओं के साथ जीवित हैं, क्योंकि ORM पास सत्र नहीं है, क्योंकि बग के कारण मेरे पास दो डेटा स्रोत हैं।

इसे हल करने के लिए, मैं श्रोता को अनुकूलित करता हूं, नष्ट करने से पहले स्पष्ट कॉल करने के लिए, और कॉल को नष्ट करने के लिए दो बार, (प्रत्येक डेटा स्रोत के लिए एक)। सुनिश्चित करना कि मेरा सत्र स्पष्ट और नष्ट हो गया था, और यदि विनाश विफल हो जाता है, तो वह कम से कम स्पष्ट था।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.