"मेमोरी लीक" की एनाटॉमी

.NET परिप्रेक्ष्य में:

  • एक मेमोरी लीक ?
  • क्या है
  • आप कैसे निर्धारित कर सकते हैं कि आपका आवेदन लीक हो गया है या नहीं? प्रभाव क्या हैं?
  • आप मेमोरी रिसाव को कैसे रोक सकते हैं?
  • यदि आपके एप्लिकेशन में मेमोरी रिसाव है, तो क्या प्रक्रिया समाप्त हो जाती है या मार डाला जाता है? या प्रक्रिया के पूरा होने के बाद भी आपके एप्लिकेशन में मेमोरी लीक सिस्टम पर अन्य प्रक्रियाओं को प्रभावित करती है?
  • और COM इंटरऑप और / या पी / Invoke के माध्यम से अप्रबंधित कोड के बारे में क्या?
0
जोड़ा संपादित
विचारों: 10

15 उत्तर

मैं मेमोरी लीक को एक ऑब्जेक्ट के रूप में परिभाषित करता हूं जो इसे पूरा होने के बाद आवंटित सभी मेमोरी को मुक्त नहीं करता है। मैंने पाया है कि यह आपके एप्लिकेशन में हो सकता है यदि आप विंडोज एपीआई और COM (यानी अप्रबंधित कोड जिसमें इसका एक बग है या सही तरीके से प्रबंधित नहीं किया जा रहा है) का उपयोग कर रहे हैं, फ्रेमवर्क और तीसरे पक्ष के घटकों में। मुझे कुछ ऑब्जेक्ट्स का उपयोग करने के बाद भी टाइडिंग नहीं मिली है जैसे पेन समस्या का कारण बन सकते हैं।

मैंने व्यक्तिगत रूप से मेमोरी अपवादों का सामना किया है जो कि कारण हो सकता है लेकिन डॉट नेट अनुप्रयोगों में मेमोरी लीक के लिए विशिष्ट नहीं है। (ओओएम पिनिंग से भी आ सकता है आर्टिकल पिनिंग ) । अगर आपको ओओएम त्रुटियां नहीं मिल रही हैं या पुष्टि करने की आवश्यकता है कि यह एक स्मृति रिसाव है तो इसका कारण है कि आपके आवेदन को प्रोफाइल करना एकमात्र तरीका है।

मैं निम्नलिखित कोशिश भी करता हूं और सुनिश्चित करता हूं:

ए) जो कुछ भी इडोजोज़ेबल लागू करता है, वह अंततः ब्लॉक या उपयोग कथन का उपयोग करके निपटान किया जाता है जिसमें ब्रश, पेन इत्यादि शामिल होते हैं (कुछ लोग तर्क देते हैं कि सबकुछ कुछ भी नहीं है)

बी) अंत में या उपयोग करने वाले कथन का उपयोग करके बंद करने की कोई भी चीज़ फिर से बंद हो जाती है (हालांकि मैंने पाया है कि अगर आप उपयोग कथन के बाहर ऑब्जेक्ट घोषित करते हैं तो इसका उपयोग हमेशा बंद नहीं होता है)

सी) यदि आप अप्रबंधित कोड / विंडोज एपीआई का उपयोग कर रहे हैं कि इन्हें सही तरीके से निपटाया जाता है। (कुछ संसाधनों को जारी करने के तरीकों को साफ कर चुके हैं)

उम्मीद है की यह मदद करेगा।

0
जोड़ा

मुझे लगता है कि एक प्रबंधित वातावरण में, एक रिसाव आप स्मृति के एक बड़े हिस्से के लिए एक अनावश्यक संदर्भ रखेंगे।

0
जोड़ा

मैं बर्नार्ड के साथ सहमत हूं कि नेट में एक मेम रिसाव क्या होगा।

आप अपने मेमोरी उपयोग को देखने के लिए अपने आवेदन को प्रोफाइल कर सकते हैं, और यह निर्धारित कर सकते हैं कि अगर यह बहुत मेमोरी का प्रबंधन करता है तो यह नहीं कह सकता कि यह एक रिसाव है।

प्रबंधित शब्दों में मैं अपनी गर्दन को लाइन पर रखूंगा कि यह कहने के बाद कि प्रक्रिया को मारने / निकालने के बाद यह दूर हो जाता है।

अप्रबंधित कोड अपने ही जानवर है और यदि इसके भीतर एक रिसाव मौजूद है, तो यह एक मानक ज्ञापन का पालन करेगा। रिसाव परिभाषा।

0
जोड़ा

मुझे लगता है कि एक प्रबंधित वातावरण में, ए   रिसाव आप एक रखेंगे   एक बड़े हिस्से के लिए अनावश्यक संदर्भ   स्मृति के आसपास।

पूर्ण रूप से। इसके अलावा, उपयुक्त होने पर डिस्पोजेबल ऑब्जेक्ट्स पर डिस्प्ले() विधि का उपयोग न करें, मेम लीक का कारण बन सकता है। ऐसा करने का सबसे आसान तरीका एक प्रयोग ब्लॉक के साथ है क्योंकि यह स्वचालित रूप से निष्पादित करता है। अंत में() अंतःस्थापित करें:

StreamReader sr;
using(sr = new StreamReader("somefile.txt"))
{
    //do some stuff
}

और यदि आप एक वर्ग बनाते हैं जो अप्रबंधित वस्तुओं का उपयोग कर रहा है, यदि आप सही ढंग से IDISposable लागू नहीं कर रहे हैं, तो आप अपने वर्ग के उपयोगकर्ताओं के लिए मेमोरी लीक का कारण बन सकते हैं।

0
जोड़ा

कड़ाई से बोलते हुए, एक स्मृति रिसाव स्मृति का उपभोग कर रहा है जो प्रोग्राम द्वारा "अब उपयोग नहीं किया जाता" है।

"अब उपयोग नहीं किया गया" का अर्थ एक से अधिक अर्थ है, इसका अर्थ यह हो सकता है कि "इसका कोई और संदर्भ नहीं है", यानी पूरी तरह से अप्राप्य है, या इसका मतलब हो सकता है, संदर्भित, पुनर्प्राप्त करने योग्य, अप्रयुक्त लेकिन कार्यक्रम वैसे भी संदर्भ रखता है। केवल बाद में पूरी तरह से प्रबंधित ऑब्जेक्ट्स के लिए नेट पर लागू होता है। हालांकि, सभी वर्ग सही नहीं हैं और किसी बिंदु पर अंतर्निहित अप्रबंधित कार्यान्वयन उस प्रक्रिया के लिए संसाधनों को स्थायी रूप से रिसाव कर सकता है।

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

आपको पता है कि किसी एप्लिकेशन में स्मृति समस्या होती है जब निगरानी करता है कि आपकी प्रक्रिया में अधिक से अधिक स्मृति आवंटित की जाती है प्रत्येक कचरा संग्रहण चक्र के बाद। ऐसे मामले में, आप या तो स्मृति में बहुत अधिक रखते हैं, या कुछ अंतर्निहित अप्रबंधित कार्यान्वयन लीक हो रहा है।

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

0
जोड़ा

मैंने जो सबसे अच्छा स्पष्टीकरण देखा है वह मुफ्त के अध्याय 7 में है प्रोग्रामिंग ईबुक की नींव

असल में, .NET में एक स्मृति रिसाव तब होती है जब संदर्भित वस्तुओं को रूट किया जाता है और इस प्रकार कचरा एकत्र नहीं किया जा सकता है। यह गलती से होता है जब आप इच्छित दायरे से परे संदर्भों को धारण करते हैं।

आपको पता चलेगा कि जब आप आउटफमेमरीएक्सप्शन प्राप्त करना शुरू करते हैं तो आपके पास लीक होती है या आपकी मेमोरी उपयोग जो आप उम्मीद करेंगे उससे परे हो जाती है (परफोन में अच्छी मेमोरी काउंटर है)।

.NET के मेमोरी मॉडल को समझना इससे बचने का आपका सबसे अच्छा तरीका है। विशेष रूप से, समझें कि कचरा कलेक्टर कैसे काम करता है और संदर्भ कैसे काम करते हैं (फिर से, मैं आपको ईबुक के अध्याय 7 में संदर्भित करता हूं)। साथ ही, सामान्य नुकसान के बारे में सावधान रहें, शायद सबसे आम घटनाएं। यदि ऑब्जेक्ट ए ऑब्जेक्ट बी पर किसी ईवेंट में पंजीकृत है, तो ऑब्जेक्ट ए ऑब्जेक्ट बी गायब होने तक चारों ओर चिपकेगा क्योंकि बी को संदर्भित किया जाता है। समाधान आपके ईवेंट को अनियंत्रित करना है जब आप पूरा कर लेंगे।

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

मेरा मानना ​​है कि अप्रबंधित कोड असम्बद्ध कोड की सामान्य मेमोरी लीक के अधीन है, सिवाय इसके कि दोनों के बीच साझा संदर्भ कचरा कलेक्टर द्वारा प्रबंधित किए जाते हैं। इस अंतिम बिंदु के बारे में गलत हो सकता है।

0
जोड़ा
@ जेफरी यह वर्णन करने का एक असंवैधानिक तरीका है कि क्या हो रहा है और मुझे यह पसंद है!
जोड़ा लेखक Exitos, स्रोत
@kyoryu: ऑब्जेक्ट स्वयं कैसे रूट करता है?
जोड़ा लेखक Andrei Rînea, स्रोत
ओह आपको किताब पसंद है? मैंने देखा है कि लेखक समय-समय पर स्टैक ओवरफ्लो पर पॉप अप करते हैं।
जोड़ा लेखक Johnno Nolan, स्रोत
कुछ .NET ऑब्जेक्ट्स स्वयं को रूट कर सकते हैं और अचयनित हो सकते हैं। इसके कारण IDISposable कुछ भी निपटान किया जाना चाहिए।
जोड़ा लेखक kyoryu, स्रोत
@Andrei: मुझे लगता है कि एक चल रहा थ्रेड शायद ऑब्जेक्ट rooting खुद का सबसे अच्छा उदाहरण है। एक ऑब्जेक्ट जो एक स्थैतिक गैर-सार्वजनिक स्थान (जैसे एक स्थैतिक घटना की सदस्यता लेना, या स्थैतिक क्षेत्र प्रारंभिक द्वारा सिंगलटन को कार्यान्वित करना) में खुद को संदर्भित करता है, क्योंकि यह भी स्पष्ट रूप से रूट हो सकता है, क्योंकि कोई स्पष्ट तरीका नहीं है ... उम ... इसे अपने मूरिंग से "उखाड़ फेंक"।
जोड़ा लेखक Jeffrey Hantin, स्रोत
अप्रबंधित / मूल कोड आमतौर पर भौतिक रिसाव के लिए अधिक असुरक्षित है लेकिन इन तार्किक / जड़ वाले लोगों के लिए इतना अधिक नहीं है। ऐसा इसलिए है क्योंकि यदि हमारे पास इन जड़ वाले संसाधनों में से एक है जो "उखाड़ फेंकने" में असफल रहता है, तो आम तौर पर वे सी जैसी भाषा में स्पष्ट रूप से नष्ट हो जाते हैं। इन मामलों में होने वाली त्रुटि अक्सर खतरनाक सूचक और अक्सर कुछ प्रकार होती है इसे एक्सेस करने के साथ जुड़े segfault का। यद्यपि कभी-कभी यह रूट संसाधन होने के लिए वास्तव में बेहतर होता है, जब तक एप्लिकेशन बंद नहीं हो जाता है (एक क्रैश बहुत अप्रिय, आसानी से पता लगाने वाला बग) होता है।
जोड़ा लेखक Team Upvote, स्रोत

कार्यक्रम की समाप्ति से सभी मेमोरी लीक का समाधान किया जाता है।

पर्याप्त स्मृति लीक करें और ऑपरेटिंग सिस्टम आपकी ओर से समस्या को हल करने का निर्णय ले सकता है।

0
जोड़ा

यदि आपको .NET में मेमोरी लीक का निदान करने की आवश्यकता है, तो इन लिंक को जांचें:

http: // msdn .microsoft.com / en-us / पत्रिका / cc163833.aspx

http: // msdn .microsoft.com / en-us / पत्रिका / cc164138.aspx

वे लेख वर्णन करते हैं कि आपकी प्रक्रिया का मेमोरी डंप कैसे बनाएं और इसका विश्लेषण कैसे करें ताकि आप पहले यह निर्धारित कर सकें कि आपका रिसाव अप्रबंधित या प्रबंधित है या नहीं, और यदि यह प्रबंधित किया जाता है, तो यह पता लगाने के लिए कि यह कहां से आ रहा है।

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

http://www.microsoft.com/downloads/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&displaylang=en

0
जोड़ा

Using CLR Profiler from Microsoft http://www.microsoft.com/downloads/details.aspx?familyid=86ce6052-d7f4-4aeb-9b7a-94635beebdda&displaylang=en is a great way to determine which objects are holding memory, what execution flow leads to the creation of these objects, and also monitoring which objects live where on the heap (fragmentation, LOH, etc.).

0
जोड़ा

यह भी ध्यान रखें कि .NET में दो ढेर हैं, एक बड़ी वस्तु ढेर है। मेरा मानना ​​है कि इस ढेर पर मोटे तौर पर 85k या बड़े की वस्तुओं को रखा जाता है। इस ढेर में नियमित ढेर की तुलना में एक अलग आजीवन नियम होते हैं।

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

जहां तक ​​आप प्रक्रिया समाप्त होने पर स्मृति को पुनः प्राप्त नहीं कर लेते हैं, जब तक कि आपके Win98 या समकक्ष नहीं चलते, सबकुछ ओएस पर समाप्त हो जाता है। केवल अपवाद ही चीजें हैं जो क्रॉस-प्रोसेस खोले जाते हैं और दूसरी प्रक्रिया में अभी भी संसाधन खुला है।

COM ऑब्जेक्ट्स मुश्किल हो सकता है। यदि आप हमेशा IDISpose पैटर्न का उपयोग करते हैं, तो आप सुरक्षित रहेंगे। लेकिन मैंने कुछ इंटरऑप असेंबली में भाग लिया है जो IDISpose को लागू करते हैं। जब आप इसके साथ काम करते हैं तो यहां कुंजी Marshal.ReleaseCOMObject को कॉल करना है। COM ऑब्जेक्ट्स अभी भी मानक COM संदर्भ गिनती का उपयोग करते हैं।

0
जोड़ा

मुझे .NET में मेमोरी लीक ढूंढते समय नेट मेमोरी प्रोफाइलर बहुत अच्छी मदद मिली। यह माइक्रोसॉफ्ट सीएलआर प्रोफाइलर की तरह मुफ़्त नहीं है, लेकिन मेरी राय में बिंदु के लिए तेज़ और अधिक है। ए

0
जोड़ा

मुझे लगता है कि "मेमोरी रिसाव क्या है" और "प्रभाव क्या हैं" प्रश्नों का उत्तर पहले ही दिया गया है, लेकिन मैं अन्य प्रश्नों पर कुछ और चीजें जोड़ना चाहता हूं ...

यह समझने के लिए कि आपका एप्लिकेशन लीक है या नहीं

एक दिलचस्प तरीका है perfmon खोलना और सभी ढेर में # बाइट्स और # Gen 2 संग्रह के लिए निशान जोड़ें, प्रत्येक मामले में केवल आपके मामले में प्रक्रिया। यदि किसी विशेष सुविधा का उपयोग करने से कुल बाइट बढ़ने का कारण बनता है, और वह स्मृति अगले जनरल 2 संग्रह के बाद आवंटित की जाती है, तो आप कह सकते हैं कि सुविधा स्मृति को लीक करती है।

कैसे रोकें

अन्य अच्छी राय दी गई है। मैं बस इतना जोड़ूंगा कि शायद .NET मेमोरी लीक का सबसे अधिक अनदेखा कारण ईवेंट हैंडलर को उन्हें हटाए बिना ऑब्जेक्ट्स में जोड़ना है। किसी ऑब्जेक्ट से जुड़ा एक इवेंट हैंडलर उस ऑब्जेक्ट के संदर्भ का एक रूप है, इसलिए सभी अन्य संदर्भों के बाद भी संग्रह को रोक देगा। हमेशा ईवेंट हैंडलर को अलग करना याद रखें ( - = सी # में सिंटैक्स का उपयोग करके)।

प्रक्रिया समाप्त होने पर रिसाव दूर हो जाती है, और COM इंटरॉप के बारे में क्या?

जब आपकी प्रक्रिया निकलती है, तो डीएलएल से दी गई किसी भी COM ऑब्जेक्ट सहित ओएस द्वारा इसकी पता स्थान में मैप की गई सभी मेमोरी पुनः प्राप्त की जाती है। तुलनात्मक रूप से शायद ही कभी, COM वस्तुओं को अलग प्रक्रियाओं से परोसा जा सकता है। इस मामले में, जब आपकी प्रक्रिया निकलती है, तब भी आप किसी भी COM सर्वर प्रक्रियाओं में आवंटित स्मृति के लिए ज़िम्मेदार हो सकते हैं।

0
जोड़ा

कचरा कलेक्टर कैसे काम करता है इसका सबसे अच्छा स्पष्टीकरण जेफ रिचर्स में है सी # के माध्यम से सीएलआर </ए> पुस्तक, (च। 20)। यह पढ़ना समझने के लिए कि कैसे वस्तुएं बनी रहती हैं, यह एक महान ग्राउंडिंग देता है।

वस्तुओं को गड़बड़ाने के सबसे आम कारणों में से एक घटना को हुक अप करना एक कक्षा से बाहर है। यदि आप एक बाहरी घटना को हुक करते हैं

जैसे

SomeExternalClass.Changed += new EventHandler(HandleIt);

और जब आप निपटान करते हैं तो इसे अनदेखा करना भूल जाते हैं, तो कुछ एक्सक्लूस क्लास आपकी कक्षा में एक रेफरी है।

जैसा ऊपर बताया गया है,

SciTech मेमोरी प्रोफाइलर आपको उन वस्तुओं की जड़ों को दिखाने में उत्कृष्ट है जो आपको संदेह है कि आप लीक कर रहे हैं।

लेकिन एक विशेष प्रकार की जांच करने का एक बहुत ही तेज़ तरीका है केवल WNDBG का उपयोग करें (आप इसे संलग्न करते समय VS.NET तत्काल विंडो में भी उपयोग कर सकते हैं):

.loadby sos mscorwks
!dumpheap -stat -type 

Now do something that you think will dispose the objects of that type (जैसे close a window). It's handy here to have a debug button somewhere that will run System.GC.Collect() a couple of times.

Then run !dumpheap -stat -type again. If the number didn't go down, or didn't go down as much as you expect, then you have a basis for further investigation. (I got this tip from a seminar given by Ingo Rammer).

0
जोड़ा

लोग क्यों सोचते हैं कि .NET में एक स्मृति रिसाव किसी अन्य रिसाव के समान नहीं है?

एक स्मृति रिसाव तब होती है जब आप संसाधन से जुड़ते हैं और इसे जाने नहीं देते हैं। आप इसे प्रबंधित और अप्रबंधित कोडिंग दोनों में कर सकते हैं।

.NET, और अन्य प्रोग्रामिंग टूल के बारे में, कचरा संग्रहण के बारे में विचार हैं, और परिस्थितियों को कम करने के अन्य तरीकों से आपके आवेदन रिसाव हो जाएंगे। लेकिन मेमोरी लीक को रोकने की सबसे अच्छी विधि यह है कि आप जिस प्लेटफॉर्म का उपयोग कर रहे हैं उस पर आपको अपने अंतर्निहित मेमोरी मॉडल को समझने की ज़रूरत है, और चीजें कैसे काम करती हैं।

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

जब अप्रबंधित कोडिंग करते हैं, तो आप आमतौर पर साफ करना सुनिश्चित करते हैं, आप जानते हैं कि आपके द्वारा धारित संसाधनों को जैनिटर की सफाई करने की आपकी ज़िम्मेदारी होगी।

दूसरी तरफ .NET में, बहुत से लोग सोचते हैं कि जीसी सब कुछ साफ कर देगा। खैर, यह आपके लिए कुछ करता है, लेकिन आपको यह सुनिश्चित करने की ज़रूरत है कि ऐसा है। .NET बहुत सारी चीज़ें लपेटता है, इसलिए आप हमेशा यह नहीं जानते कि आप किसी प्रबंधित या अप्रबंधित संसाधन से निपट रहे हैं, और आपको यह सुनिश्चित करना होगा कि आप किस चीज से निपट रहे हैं। हैंडलिंग फोंट, जीडीआई संसाधन, सक्रिय निर्देशिका, डेटाबेस इत्यादि आमतौर पर चीजों की आवश्यकता होती है जिन्हें आप देखना चाहते हैं।

प्रबंधित शब्दों में मैं अपनी गर्दन को रखूंगा   यह कहने की रेखा एक बार चली जाती है   प्रक्रिया मारे / हटा दी गई है।

मुझे लगता है कि बहुत से लोगों के पास यह है, और मुझे उम्मीद है कि यह खत्म हो जाएगा। आप उपयोगकर्ता को अपनी गड़बड़ी को साफ करने के लिए अपने ऐप को समाप्त करने के लिए नहीं कह सकते हैं! एक ब्राउज़र पर एक नज़र डालें, जो आईई, एफएफ इत्यादि हो सकता है, फिर, Google रीडर खोलें, इसे कुछ दिनों तक रहने दें, और देखें कि क्या होता है।

यदि आप ब्राउज़र में एक और टैब खोलते हैं, तो किसी साइट पर सर्फ करें, फिर ब्राउज़र को रिसाव करने वाले दूसरे पेज को होस्ट करने वाले टैब को बंद करें, क्या आपको लगता है कि ब्राउज़र मेमोरी जारी करेगा? आईई के साथ ऐसा नहीं है। यदि मैं Google रीडर का उपयोग करता हूं तो मेरे कंप्यूटर पर आईई आसानी से थोड़ी सी अवधि (लगभग 3-4 दिन) में 1 जीबी मेमोरी खाएगा। कुछ समाचार पत्र भी बदतर हैं।

0
जोड़ा

One definition is: Unable to release unreachable memory, which can no longer be allocated to new process during execution of allocating process. It can mostly be cured by using GC techniques or detected by automated tools.

अधिक जानकारी के लिए, कृपया http://all-about-java-and-weblogic-server.blogspot.in/2014/01/what-is-memory-leak-in-java.html

0
जोड़ा