2009-08-15 24 views
48

जावा मानक एपीआई किस कक्षाएं मेमोरी लीक (नहीं स्पष्ट रूप से) गलत तरह से एक में जब इस्तेमाल किया पैदा कर सकता है? और इन स्मृति रिसावों से कैसे बचा जा सकता है/तय किया जा सकता है?जावा मानक एपीआई में मेमोरी रिसाव जाल

उदाहरण:ObjectInputStream और ObjectOutputStream सभी वस्तुओं वे आदेश प्रतियां संदर्भ के बजाय के रूप में एक ही वस्तु के बाद आवृत्तियां भेजने के लिए (और इस तरह वृत्तीय संदर्भ के साथ सौदा) करने के लिए देखा है के लिए संदर्भ रहते हैं। यह एक स्मृति रिसाव का कारण बनता है जब आप ऐसी स्ट्रीम को अनिश्चित काल तक खोलते हैं (उदाहरण के लिए नेटवर्क पर संवाद करने के लिए इसका उपयोग करते समय)।

फिक्स: कॉल रीसेट() समय-समय पर या प्रत्येक शीर्ष स्तर वस्तु के बाद।

+3

@ माइकल - शायद आपके उदाहरण को उत्तर में ले जाएं? –

उत्तर

46

एक बड़ा एक है कि जावा तार के सबस्ट्रिंग हो रही मूल स्ट्रिंग के लिए संदर्भित करता है।

उदाहरण: आप 3000 वर्ण रिकॉर्ड में पढ़ते हैं और 12 वर्णों का एक सबस्ट्रिंग प्राप्त करते हैं, जो कॉलर को (उसी JVM के भीतर) लौटाते हैं। भले ही आपके पास मूल स्ट्रिंग का संदर्भ न हो, फिर भी 12 वर्ण स्ट्रिंग अभी भी स्मृति में 3000 अक्षरों का उपयोग कर रही है।

प्रणाली है कि प्राप्त करते हैं और उसके बाद में बहुत से संदेश पार्स के लिए, यह एक वास्तविक समस्या हो सकती है।

String sub = new String(str.substring(6,12)); 

या

String sub = str.substring(6,12).intern(); 

पहले अधिक एकदम स्पष्ट है:

आप तरीके इस से बचने के लिए की एक जोड़ी है। दूसरे के अन्य प्रभाव हैं क्योंकि आप PermGen स्पेस का उपयोग कर रहे हैं। अत्यधिक उपयोग किया जाता है जब तक आप अपना वीएम पर्याप्त नहीं देते हैं।

याद रखें यह केवल प्रासंगिक है अगर आप छोटे सबस्ट्रिंग ले जा रहे हैं और फिर मूल स्ट्रिंग दूर फेंक और आप इस एक बहुत कुछ कर रहे हैं।

+1

एक साधारण फिक्स का उल्लेख करने के बारे में कैसे एक नई स्ट्रिंग ऑब्जेक्ट को स्पष्ट रूप से बनाना? –

+0

एक बहुत पुराना धागा टक्कर नहीं देना है, लेकिन इसका कारण क्या है? यह लाइन "str = str.substring (6,12)" क्यों केवल 6 की बजाय 3k वर्णों की एक जगह बर्बाद कर देगी? –

+2

@ मुरत: एक पुरानी टिप्पणी बंपिंग: क्योंकि यह आंतरिक स्ट्रिंग के रूप में आंतरिक रूप से एक ही चार सरणी को संदर्भित करता है, बस एक अलग ऑफसेट और लंबाई के साथ। यदि आप बहुत अधिक ओवरलैपिंग सबस्ट्रिंग बनाते हैं, तो यह वास्तव में स्मृति बचाता है। –

4

निपटाने() विधि के साथ कोई भी वर्ग?

उदाहरण java.awt.Window#dispose के लिए:

सार्वजनिक शून्य निपटाने()

विज्ञप्ति अपने स्वामित्व वाली बच्चों की इस विंडो, इसके उप-घटक द्वारा प्रयोग किया जाता देशी स्क्रीन संसाधनों के सभी, और सब। यही है, इन घटकों के संसाधनों को नष्ट कर दिया जाएगा, वे जो भी स्मृति उपभोग करते हैं उन्हें ओएस में वापस कर दिया जाएगा, और उन्हें अपरिहार्य के रूप में चिह्नित किया जाएगा।

8

जो भी आप किसी ईवेंट के प्राप्तकर्ता के रूप में पंजीकृत करते हैं, उदा। जीयूआई चौखटे में, कचरा जब तक यह पंजीकृत किया गया है और घटना स्रोत जीवित है एकत्र नहीं किया जा सकता है।

यह डेवलपर को ईवेंट स्रोत से इवेंट ग्राहक से मजबूत संदर्भ के बारे में पता नहीं है, तो यह स्मृति रिसाव पेश कर सकता है।

+0

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

+0

यह स्मृति रिसाव के लिए लगभग मानक उदाहरण है, क्योंकि यह अभी तक भूलना आसान है। –

5

थ्रेड का प्रत्येक त्वरण एक स्टैक के लिए स्मृति आवंटित करता है (डिफ़ॉल्ट 512k, -Xss के माध्यम से ट्यून करने योग्य)।यह जैसे के रूप में एक रिसाव नहीं है, लेकिन एक आवेदन के भारी बहु-धागे के लिए एक बेवकूफ प्रयास के परिणामस्वरूप स्मृति की एक बड़ी गैर-स्पष्ट खपत होगी।

+3

दरअसल, यदि आप थ्रेड ऑब्जेक्ट्स बनाते हैं और स्टार्ट() शुरू नहीं करते हैं तो यह पूरी तरह से रिसाव में बदल सकता है - स्टैक मेमोरी को फिर से पुनः प्राप्त नहीं किया जाता है, आईआईआरसी। –

+0

दिलचस्प। उसे नहीं पता था। –

+2

@ माइकल बोर्गवर्ड: मुझे नहीं लगता कि यह मामला है; क्या आपके पास कोई ज़रिया है? \ [संपादित करें \]: ऐसा लगता है कि यह JVM के पुराने संस्करणों में एक बग हो सकता है, लेकिन जावा 5 में तय किया जाना चाहिए। – Miles

7

बाहरी कक्षाओं में आपके द्वारा बनाए गए किसी भी गैर स्थैतिक आंतरिक कक्षाएं। तो निर्दोष दिखने वाली आंतरिक कक्षा विशाल ऑब्जेक्ट ग्राफ़ पर हो सकती है। उदाहरण को किसी स्थिर या एप्लिकेशन-व्यापी संग्रह में कहीं भी रखें और आप लॉट मेमोरी का उपयोग कर रहे हैं जिसका उपयोग आप नहीं कर रहे हैं।

3

मजबूत संदर्भों का उपयोग जब कमजोर संदर्भ पर्याप्त थे। आवेदन और एपीआई जो अपना स्वयं का राज्य और संसाधन प्रबंधन करते हैं, यहां सामान्य अपराधी हैं।

फिर, पर्यवेक्षक पैटर्न का उपयोग होता है, जो स्मृति रिसाव का कारण बन सकता है - जब पर्यवेक्षक विषय से खुद को हटा देता है, तब तक स्मृति को पुन: दावा नहीं किया जा सकता जब तक कि विषय पर्यवेक्षक/श्रोता के संदर्भ को भी जारी नहीं करता। यह पहले से ही पहले ही बताया गया है, लेकिन बहुत से लोगों को एहसास नहीं है कि यहां तक ​​कि लॉगर्स पर्यवेक्षक भी हैं।

इसके अतिरिक्त, there is the likelihood of classes, whose objects when instantiated are automatically placed into a static member। इनमें से कुछ वर्गों में रिलीज() या एक निपटान() विधि भी नहीं है, इसलिए स्थिर सदस्य द्वारा संदर्भ जारी रहेगा। अंततः मेमोरी लीक की इस किस्म के परिणामस्वरूप आउटऑफमेमरी त्रुटि में परिणाम होता है जिसमें परमजेन स्पेस इश्यू मूल कारण के रूप में रिपोर्ट किया जाता है, जिससे इसे निदान करना अधिक कठिन हो जाता है।

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