2012-11-20 16 views
18

मेरे पास जावा वेब एप्लिकेशन टॉमकैट 7 पर चल रहा है जिसमें एक मेमोरी लीक दिखाई देती है। लोड के दौरान जब आवेदन के औसत स्मृति उपयोग रैखिक रूप से बढ़ता है (JConsole का उपयोग करके निर्धारित)। स्मृति उपयोग पठार तक पहुंचने के बाद, प्रदर्शन में काफी कमी आई है। प्रतिक्रिया समय ~ 100ms से [300ms, 2500ms] तक जाते हैं, इसलिए यह वास्तव में वास्तविक समस्याएं पैदा कर रहा है।जावा वेब एप्लिकेशन में मेमोरी लीक

अपने आवेदन की JConsole स्मृति प्रोफाइल: application memory profile

VisualVM का उपयोग करना, मुझे लगता है कि कम से कम आधा स्मृति चरित्र सरणियों द्वारा किया जा रहा है (यानी चार []) और है कि ज्यादातर (मोटे तौर पर एक ही नंबर तारों में से प्रत्येक के 300,000 उदाहरण) में से एक हैं: "आवंटन विफलता", "प्रतिलिपि", "मामूली जीसी का अंत", जिनमें से सभी कचरा संग्रहण अधिसूचना से संबंधित प्रतीत होते हैं। जहां तक ​​मुझे पता है, एप्लिकेशन कचरा कलेक्टर की निगरानी नहीं करता है। VisualVM को इनमें से किसी भी स्ट्रिंग के लिए जीसी रूट नहीं मिल रहा है, इसलिए मुझे इसे ट्रैक करने में कठिनाई हो रही है।

मेमोरी विश्लेषक हीप डंप: heap dump, unreachable memory

मैं व्याख्या नहीं कर सकते क्यों कि जैसे स्मृति उपयोग पठारों, लेकिन मैं क्यों प्रदर्शन खराब हो एक बार यह होता है के रूप में एक सिद्धांत है। अगर स्मृति खंडित है, तो आवेदन को नए अनुरोधों को संभालने के लिए स्मृति के एक संगत ब्लॉक को आवंटित करने में काफी समय लग सकता है।

इसे अंतर्निहित टॉमकैट सर्वर स्थिति अनुप्रयोग की तुलना में, स्मृति बढ़ता है और स्तर बंद हो जाता है, लेकिन मेरे आवेदन की तरह उच्च "मंजिल" नहीं मारा जाता है। इसमें पहुंचने योग्य चार [] की उच्च संख्या भी नहीं है।

बिलाव सर्वर स्थिति आवेदन की JConsole स्मृति प्रोफाइल: enter image description here

बिलाव सर्वर स्थिति applicationp की मेमोरी विश्लेषक हीप डंप: enter image description here

जहां इन तार आवंटित और क्यों किया जा सकता है वे नहीं हैं कचरा इकट्ठा किया जा रहा है? क्या टोमकैट या जावा सेटिंग्स हैं जो इससे प्रभावित हो सकती हैं? क्या ऐसे विशिष्ट पैकेज हैं जो इस पर असर डाल सकते हैं?

+0

आपने यह कैसे निर्धारित किया कि विशेष रूप से उन तारों को जीसीड नहीं किया जा रहा है? – djechlin

+0

जब मेरा एप्लिकेशन निष्क्रिय है, तो मैं कचरा संग्रह को मजबूर करता हूं और VisualVM का उपयोग करके एक ढेर डंप लेता हूं। इन तारों की संख्या हमेशा समय के साथ बढ़ जाती है और हमेशा कम से कम आधे उपयोग की गई स्मृति के लिए खाते हैं। –

+0

मेमोरी विश्लेषक इंगित करता है कि पहुंचने योग्य char [] और स्ट्रिंग ऑब्जेक्ट्स 210 एमबी ढेर के 176 एमबी के लिए खाते हैं। –

उत्तर

6

मैं tomcat\bin\setenv.bat से निम्नलिखित JMX विन्यास हटाया:

set "JAVA_OPTS=%JAVA_OPTS% 
    -Dcom.sun.management.jmxremote=true 
    -Dcom.sun.management.jmxremote.port=9090 
    -Dcom.sun.management.jmxremote.ssl=false 
    -Dcom.sun.management.jmxremote.authenticate=false" 

मैं विस्तृत स्मृति नहीं मिल सकता है ढेर अब डंप करता है, लेकिन मेमोरी प्रोफाइल बहुत बेहतर दिखता है: enter image description here

24 घंटे बाद, स्मृति प्रोफ़ाइल एक ही दिखता है: enter image description here

3

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

+0

मेमोरी विश्लेषक पुष्टि करता है कि VisualVM क्या इंगित करता है; पहुंचने योग्य चार [] और स्ट्रिंग ऑब्जेक्ट्स 210 एमबी ढेर के लगभग 176 एमबी के लिए खाते हैं। दुर्भाग्यवश, यह यह समझाने में मदद नहीं करता है कि तार कहां से आ रहे हैं या क्यों वे कचरा नहीं जा रहे हैं। –

+0

मैं आपकी पहुंच योग्य वस्तुओं की जांच करने की कोशिश करता हूं, न कि आपके पहुंचने योग्य, मुझे लगता है कि समस्या वहां है। – Zamir

0

जैसा कि यह अनिश्चित लगता है, एक उम्मीदवार जेएसएफ होता। लेकिन फिर मैं हैश नक्शे भी लीक होने की उम्मीद करता।

आप JSF का उपयोग करना चाहिए: web.xml में आप की कोशिश कर सकते:

  • javax.faces.STATE_SAVING_METHOD ग्राहक
  • com.sun.faces.numberOfViewsInSession
  • com.sun.faces।numberOfLogicalViews

उपकरणों के लिए के रूप में: JavaMelody नित्य आँकड़ों के लिए दिलचस्प हो सकता है, लेकिन प्रयास की जरूरत है।

2

मैं jvisualvm की सिफारिश कर सकता हूं जो प्रत्येक जावा स्थापना के साथ आता है। प्रोग्राम शुरू करें, अपने वेबप्लिकेशंस से कनेक्ट करें। पर जाएं मॉनिटर -> हीप डंप। अब इसमें कुछ समय लग सकता है (आकार के आधार पर)। हीप डंप के माध्यम से नेविगेशन काफी आसान है, लेकिन इसका मतलब है कि आपको खुद को समझना है (हालांकि जटिल नहीं है), उदा।

जाओ को कक्षा (heapdump के अंदर), java.lang.String चयन , सही दिखाएं क्लिक करें में उदाहरण देखें। इसके बाद आप बाईं तरफ तालिकास्ट्रिंग वर्तमान में आपके सिस्टम में सक्रिय उदाहरण देखेंगे। Klick एक स्ट्रिंग उदाहरण पर और आप स्ट्रिंग की मूल्य तरह राइट ऊपरी सही टेबल की ओर से कुछ स्ट्रिंग preferenes भी दिखाई देगा।

सही तालिका के निचले दाएं भाग पर आप जहां इसस्ट्रिंग उदाहरण से संदर्भित है देखेंगे। यहां आपको यह जांचना होगा कि आपके अधिकांश * स्ट्रिंग * का संदर्भ कहां से किया जा रहा है। लेकिन आपके मामले के साथ (176/210, कुछ स्ट्रिंग उदाहरणों को खोजने के लिए अच्छी संभावना है जो आपकी समस्याओं का शीघ्रता से कारण बनती हैं) यह कुछ निरीक्षण के बाद स्पष्ट होना चाहिए जहां समस्या निहित है।

+0

मैंने पहले ही एक हीप डंप प्राप्त करने के लिए JVisualVM का उपयोग किया है, और मेमोरी विश्लेषक इंगित करता है कि "लीकिंग" वाले तार पहुंचने योग्य नहीं हैं (यानी उनके पास कुछ भी संदर्भ नहीं है), और मुझे पता नहीं लगाया गया कि उन्हें क्या आवंटित किया गया है। –

2

पठार डिफ़ॉल्ट प्रतिशत सीमा से नीचे उपलब्ध स्मृति के कारण होता है जो पूर्ण जीसी का कारण बनता है। यह बताता है कि प्रदर्शन क्यों गिरता है क्योंकि JVM लगातार रोक रहा है जबकि यह खोजने और मुक्त स्मृति खोजने का प्रयास करता है।

मैं आमतौर पर ऑब्जेक्ट कैश को देखने की सलाह देता हूं लेकिन आपके मामले में मुझे लगता है कि आपका हीप आकार टॉमकैट इंस्टेंस + वेबएप के लिए बहुत कम है। मैं आपकी ढेर को 1 जी (-Xms1024m -Xmx1024m) में बढ़ाने की सलाह दूंगा और फिर अपने मेमोरी उपयोग की फिर से समीक्षा करूंगा।

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

एक बार जब आप अपनी मेमोरी उपयोग को समझ लेते हैं, तो आप इसे फिर से कम करने में सक्षम हो सकते हैं लेकिन IMHO 512MB न्यूनतम होगा।

अद्यतन:

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

2

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

मेमोरी विश्लेषक

Memory Analyzer

पूर्ण जीसी अब हर 2s चल रहा है, लेकिन उन स्ट्रिंग्स एकत्र न हो जाएं। मेरा अनुमान है कि हमने जीसी कोड में एक बग मारा है।

$ java -version 
java version "1.7.0_06" 
Java(TM) SE Runtime Environment (build 1.7.0_06-b24) 
Java HotSpot(TM) 64-Bit Server VM (build 23.2-b09, mixed mode) 

और निम्नलिखित वीएम पैरामीटर:: हम निम्नलिखित जावा संस्करण का उपयोग

-Xms256m -Xmx768m -server -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC 
-XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:NewSize=32m -XX:MaxNewSize=64m 
-XX:SurvivorRatio=8 -verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails 
-Xloggc:/path/to/file 
+0

मुझे यह नोट [मेमोरी विश्लेषक के लिए प्रलेखन] (http://wiki.eclipse.org/MemoryAnalyzer/FAQ) में मिला है जो इंगित करता है कि यह एक बग के बजाय "सामान्य" जीसी व्यवहार हो सकता है: "इंडेक्स के दौरान सृजन, मेमोरी विश्लेषक पहुंचने योग्य वस्तुओं को हटा देता है क्योंकि विभिन्न कचरा कलेक्टर एल्गोरिदम कुछ कचरा छोड़ देते हैं (यदि वस्तु बहुत छोटी है, तो चलती है और पते को फिर से असाइन करना महंगा है)। हालांकि, यह 3 से अधिक नहीं होना चाहिए 4 प्रतिशत। " –

1

दुर्घटना, मैं हमारे बिलाव के conf/catalina.properties फ़ाइल में निम्नलिखित लाइनों कि स्ट्रिंग कैशिंग को सक्रिय भर में ठोकर खाई। यदि आपके पास उनमें से कोई भी चालू है तो यह आपके मामले से संबंधित हो सकता है। यह सुविधा का उपयोग करने के लिए others are warning लगता है।

tomcat.util.buf.StringCache.byte.enabled=true 
#tomcat.util.buf.StringCache.char.enabled=true 
#tomcat.util.buf.StringCache.trainThreshold=500000 
#tomcat.util.buf.StringCache.cacheSize=5000 
0

कोशिश मेट का उपयोग करें और यह सुनिश्चित करें कि जब आप heapdump पार्स, यह नहीं पहुंचा जा सकता वस्तुओं छोड़ने नहीं है बनाने के लिए।

ऐसा करने के लिए, ट्यूटोरियल here का पालन करें।

तो फिर तुम एक साधारण मेम रिसाव विश्लेषण (This एक अच्छा ट्यूटोरियल है)

कि जल्दी से मूल कारण तक ले जाना चाहिए चला सकते हैं।

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