2012-03-05 21 views
6

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

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

समस्या, जैसा कि पहले संकेत दिया गया है, यह है कि समय के बाद, एप्लिकेशन OutOfMemoryError: जावा हीप स्पेस के साथ क्रैश हो रहा है। मैंने ग्रहण + मैट का उपयोग करके एक हीप-डंप को देखा है, और अपराधियों को हाइबरनेट के सत्र के रूप में पहचाना है फैक्ट्रीऑब्जेक्ट फैक्ट्री, आवंटित स्मृति का लगभग 85% (इसे सभी याद रखने वाली स्मृति) लेते हैं। मुझे यह पता लगाने में थोड़ा मुश्किल लगा है कि इस प्रकार किस प्रकार की वस्तुओं को रखा जाता है। शीर्ष स्तर पर ग्लासफ़िश WebappClassLoader है, जिसमें org.hibernate.impl.SessionFactoryObjectFactory शामिल है। इसमें एक org.hibernate.util.FastHashMap है, जो बदले में java.util.HashMap है। इसमें कई प्रविष्टियां हैं, जिनमें से प्रत्येक में हैश मैप-एंट्री, एक org.hibernate.impl.SessionFactoryImpl और एक स्ट्रिंग शामिल है। बदले में हैश मैप-एंट्री में एक ही तीन ऑब्जेक्ट्स, हैश मैप-एंट्री, एक सत्र फैक्ट्रीआईएमपीएल और स्ट्रिंग शामिल है, और यह संरचना कई बार खुद को दोहराती है। सत्र फ़ैक्टरीइम्पल्स में कई ऑब्जेक्ट्स हैं, विशेष रूप से org.hibernate.persister.entity.SingleTableEntityPersister, जिसमें कई स्ट्रिंग्स और हैश मैप्स शामिल हैं। कुछ स्ट्रिंग्स डोमेन ऑब्जेक्ट्स में वेरिएबल्स को संदर्भित करती हैं, और कुछ में SQL-स्टेटमेंट होते हैं।

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

फिर, मैंने इसका कारण खोजने की कोशिश की, लेकिन यह बहुत कठिन था। जैसे ही हाइबरनेट द्वारा लोड की गई वस्तुएं तब तक रहेंगी जब तक उनका सत्र रहता है, मैंने स्प्रिंग्स के हाइबरनेटडेटो सपोर्ट # getSession() को कॉल को प्रतिस्थापित करके, सत्रों को संभालने के तरीके को बदलने की कोशिश की, HibernateDaoSupport # getSessionFactory()। GetCurrentSession()। इस समस्या पर कोई प्रभावशाली प्रभाव नहीं पड़ा। मैंने कॉल में कुछ डाओ-विधियों के आखिरकार ब्लॉक में getCurrentSession()। Flush() और .clear() को कॉल जोड़ने का भी प्रयास किया, बिना किसी प्रभावशाली प्रभाव के। (दाओ-विधियों को सभी @ ट्रांसेक्शनल के साथ एनोटेटेड किया गया है, जिसका अर्थ यह होना चाहिए कि सत्र केवल ट्रांजैक्शनल-विधि के भीतर ही जीवित होना चाहिए, और विधि को लगातार कॉल करने के लिए अलग-अलग सत्र प्राप्त करना चाहिए जब getCurrentSession() (?))

तो, अब जब मैं जांच के लिए अन्य क्षेत्रों के साथ आने की बात आती हूं तो मैं काफी अटक गया हूं। क्या किसी के पास कोई विचार या कुछ पॉइंटर है कि कहां देखना है और क्या देखना है?

ढेर-डंप ने दिखाया कि org.hibernate.impl.SessionFactoryImpl के कई उदाहरण हैं, क्या यह अपेक्षित है? (मैंने सोचा होगा कि केवल सत्र कारखाना, या कुछ शीर्ष का एक उदाहरण होना चाहिए।)

कोई जवाब के लिए अग्रिम धन्यवाद।

सादर,

Tobb

संपादित करें:

मुझे लगता है कि मैं वास्तव में समस्या को हल करने mananged है:

ऐसा नहीं है कि जिस तरह से अन्य वस्तुओं के लिए उनकी निर्भरता में संचालन हुआ निकला webservice-classesस समस्या थी। यह webservice कक्षाओं के निर्माता में नए ClassPathXmlAplicationContext (...) को कॉल करके हल किया गया था। इससे प्रत्येक अनुरोध (या कम से कम प्रत्येक सत्र) के लिए बहुत सारी वस्तुओं को लोड किया जा रहा था, जिन्हें फिर से अनलोड नहीं किया गया था (मुख्य रूप से हाइबरनेट का सत्र फ़ैक्टरीइम्पल)। मैंने webservice-classesर्थों को बदल दिया है, इसलिए वे इसके निर्भरता को इंजेक्ट करते हैं, और जो मैंने अब तक प्रोफाइलर्स का उपयोग करके देखा है, कई सत्र FactoryImpl-ऑब्जेक्ट्स के साथ समस्या हल हो गई है।

मुझे लगता है कि समस्या हो सकती है ग्लासफिश 3.x के लिए ग्लासफिश 2.x से उन्नयन से बदतर कर दिया है, कैसे वेब सेवा वर्गों instantiated कर रहे हैं के रूप में कुछ मतभेद हो सकता है।

उत्तर

5

मैं भी समाधान इस समस्या का एक जवाब में, के बजाय सिर्फ सवाल अपने आप में जोड़ सकते हैं:

अपराधी यहाँ कैसे वसंत-सेम की लोडिंग विभिन्न वस्तुओं में किया गया था, सबसे विशेष रूप में किया गया था वेब सेवा वर्गों। यह

new ClassPathXmlApplicationContext(...)

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

public class ContextHolder { 
    private static ClassPathXmlApplicationContext context; 

    public static getSpringContext() { 
     if (context == null) { 
      context = new ClassPathXmlApplicationContext("applicationContext.xml"); 
     } 
     return context; 
    } 
} 

और इस बुला:

समस्या का समाधान स्थिर कारखाने में पैटर्न कुछ इस तरह का उपयोग कर, एक अलग वर्ग में बाहर

new ClassPathXmlApplicationContext(...)

के लिए कॉल स्थानांतरित करने के लिए किया गया था, websPathXmlAplicationContext के नए-इन के बजाय webservice-classes।

अद्यतन:

ClassPathXmlApplicationContextCloseable/Autocloseable है, इसलिए try-with-resource एक और संभावना है:

try (final ClassPathXmlApplicationContext applicationContext = 
      new ClassPathXmlApplicationContext("applicationContext.xml")) { 
    //do stuff 
} 
+0

वैकल्पिक रूप से स्थिर कारखाने के लिए, मुझे लगता है कि 'ClassPathXmlApplicationContext' एक' close'-विधि है कि हो सकता है इस समस्या से बचने के लिए बुलाया। – Tobb

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

  • कोई संबंधित समस्या नहीं^_^