Android में कचरा संग्रहकर्ता


108

मैंने कई एंड्रॉइड उत्तर देखे हैं जो कुछ स्थितियों में कचरा कलेक्टर को कॉल करने का सुझाव देते हैं।

मेमोरी-भूखा संचालन करने से पहले एंड्रॉइड में कचरा कलेक्टर से अनुरोध करना एक अच्छा अभ्यास है? यदि नहीं, तो क्या मुझे OutOfMemoryत्रुटि मिलने पर ही फोन करना चाहिए ?

क्या कचरे के संग्रहकर्ता का सहारा लेने से पहले मुझे अन्य चीजों का उपयोग करना चाहिए?

जवाबों:


144

3.0 हनीकॉम्ब से पहले के संस्करणों के लिए : हां, कॉल करें System.gc()

मैंने बिटमैप बनाने की कोशिश की, लेकिन हमेशा "वीएम आउट ऑफ मेमोरी एरर" मिल रहा था। लेकिन, जब मैंने System.gc()पहली बार फोन किया , तो यह ठीक था।

बिटमैप बनाते समय, एंड्रॉइड अक्सर मेमोरी त्रुटियों से बाहर निकलता है, और पहले कचरा इकट्ठा करने की कोशिश नहीं करता है । इसलिए, कॉल करें System.gc(), और आपके पास बिटमैप बनाने के लिए पर्याप्त मेमोरी है।

यदि ऑब्जेक्ट्स बनाते हैं, तो मुझे लगता है System.gcकि ज़रूरत पड़ने पर स्वचालित रूप से कॉल किया जाएगा, लेकिन बिटमैप बनाने के लिए नहीं । यह बस विफल हो जाता है।

इसलिए मैं System.gc()बिटमैप बनाने से पहले मैन्युअल रूप से कॉल करने की सलाह देता हूं ।


39
ऐसा इसलिए है क्योंकि प्री-हनीकॉम्ब, बिटमैप डेटा VM में संग्रहीत नहीं है और इसलिए यह GC को ट्रिगर नहीं करेगा। यह हनीकॉम्ब और बाद में समस्या नहीं होनी चाहिए।
18mm पर टिम्मम

2
@ टिममम, लेकिन यह वास्तव में मेरी समस्या थी, मैंने केवल सचाई के लिए बड़ेपन को निर्धारित किया था।
लेई लेबेबा

118

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

कभी-कभी , कुछ अपेक्षाकृत दुर्लभ स्थितियों में, कोई यह पा सकता है कि किसी विशेष GC को यह गलत लगता है, और GC को मैन्युअल कॉल करने से चीजों, प्रदर्शन-वार में सुधार हो सकता है। ऐसा इसलिए है क्योंकि "परिपूर्ण" जीसी को लागू करना वास्तव में संभव नहीं है जो सभी मामलों में स्मृति को बेहतर तरीके से प्रबंधित करेगा। इस तरह की स्थितियों का अनुमान लगाना कठिन है और कई सूक्ष्म कार्यान्वयन विवरणों पर निर्भर हैं। "अच्छा अभ्यास" जीसी को खुद से चलने देना है; जीसी के लिए एक मैनुअल कॉल अपवाद है, जिसे वास्तविक प्रदर्शन के मुद्दे के विधिवत रूप से देखे जाने के बाद ही लागू किया जाना चाहिए।


8
एक अच्छा प्लेटफ़ॉर्म-स्वतंत्र उत्तर के लिए +1। यह देखने के लिए प्रतीक्षा करना कि क्या कोई व्यक्ति चुनने से पहले एंड्रॉइड-विशिष्ट उत्तर के साथ आता है।
hpique

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

5
खेल में यह अक्सर महत्वपूर्ण होता है कि जीसी नहीं चलता है जबकि खेल चल रहा है (इसके लिए आवश्यक है कि सभी ऑब्जेक्ट पूर्व-निर्मित और पुनर्नवीनीकरण या समान हों), लेकिन जब खेल को रोक दिया जाता है तो यह जीसी के लिए एक अच्छा समय होता है।
पैट

4
पूर्व-छत्ते, बिटमैप डेटा को वीएम मेमोरी में संग्रहीत नहीं किया जाता है। सिस्टम पता नहीं लगाएगा कि आपने बिटमैप के कारण बहुत अधिक गैर-वीएम मेमोरी का उपयोग किया है और जीसी (जो Bitmap.finalize()गैर-वीएम मेमोरी को मुक्त करने वाले तरीकों को चलाएगा )। इसलिए इस मामले में, आपको जीसी के सिर के ऊपर जाना चाहिए और दौड़ना चाहिए Bitmap.recycle()या System.gc()जहां उपयुक्त हो। लेकिन केवल पूर्व मधुकोश।
टिम्मम्म

1
@ThomasPornin - दूसरी ओर, एप्लिकेशन प्रोग्रामर के रूप में, आप कुछ ऐसा जानते हैं जो OS नहीं जानता है: कई बार आपका ऐप अब किस तरह से मेमोरी में उपयोग करता है, इसमें एक बड़ा बदलाव करने जा रहा है , और यह कम विघटनकारी होगा भविष्य में एक मनमाने समय की तुलना में उपयोगकर्ता अब एक विराम लेने का अनुभव करता है । इसका मतलब यह है कि एप्लिकेशन का उपयोग कैसे किया जा रहा है , इस बारे में प्रमुख बदलावों में , अनौपचारिक कॉल करने के लिए समझदार हो सकता है। ये इस मायने में दुर्लभ हैं कि किसी को जीसी को बार-बार कॉल नहीं करना चाहिए, लेकिन यह सामान्य है कि लगभग किसी भी महत्वपूर्ण ऐप में इस तरह के ज्ञात क्षण होते हैं।
ToolmakerSteve

26

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

if(imageBitmap != null) {
    imageBitmap.recycle();
    imageBitmap = null;
}
System.gc();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 3;
imageBitmap = BitmapFactory.decodeFile(URI, options);
Bitmap  scaledBitmap = Bitmap.createScaledBitmap(imageBitmap, 200, 200, true);
imageView.setImageBitmap(scaledBitmap);

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

यदि फिर भी समस्या का सामना करना पड़ रहा है तो आप इन रेखाओं को भी जोड़ सकते हैं

BitmapFactory.Options options = new BitmapFactory.Options();
options.inTempStorage = new byte[16*1024];
options.inPurgeable = true;

अधिक जानकारी के लिए इस लिंक पर एक नज़र डालें

https://web.archive.org/web/20140514092802/http://voices.yahoo.com/android-virtual-machine-vm-out-memory-error-7342266.html?cat=59


नोट: जीसी प्रदर्शन के कारण क्षणिक "ठहराव" के कारण, प्रत्येक बिटमैप आवंटन से पहले ऐसा करने की अनुशंसा नहीं की जाती है ।

इष्टतम डिजाइन है:

  1. मुक्त सभी बिटमैप्स कि अब जरूरत है , से if / recycle / nullपता चला कोड। (उस के साथ मदद करने के लिए एक विधि बनाओ।)

  2. System.gc();

  3. नए बिटमैप आवंटित करें।


19

यदि आपको OutOfMemoryError मिलती है, तो आमतौर पर कचरा संग्रहकर्ता को कॉल करने में बहुत देर हो जाती है ...

यहाँ Android डेवलपर से बोली है:

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

तो मेरी समझ में, gc को कॉल करने की कोई तत्काल आवश्यकता नहीं है। वस्तुओं के अनावश्यक निर्माण से बचने के लिए अधिक प्रयास करना बेहतर है (जैसे छोरों के अंदर वस्तुओं का निर्माण)


6
क्या दूसरे तरीके से उद्धरण की व्याख्या नहीं की जा सकती है? हो सकता है कि बहुत अधिक मेमोरी का उपभोग करने से पहले उन वस्तुओं को इकट्ठा करने के लिए जीसी को मैन्युअल रूप से बुलाया जाए।
hpique

@hgpc: मैं यह नहीं देखता कि बोली की व्याख्या आपके सुझाव के तरीके से कैसे की जा सकती है। मुझे लगता है कि प्रलेखन एक स्वीकारोक्ति है, यह स्वीकार करते हुए कि उनकी जीसी सरल है; जब स्मृति कम चलती है, तो एक पूर्ण GC निष्पादित किया जाता है।
राष्ट्रपति जेम्स के। पोल्क

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

9

ऐसा लगता है System.gc()कि आर्ट एंड्रॉइड 6.0.1 नेक्सस 5x पर काम नहीं करता है, इसलिए मैं Runtime.getRuntime().gc();इसके बजाय उपयोग करता हूं ।


1
System.gc()के लिए एक आवरण समारोह है Runtime.getRuntime().gc()। देखें android.googlesource.com/platform/libcore/+/…-
नाथन एफ।

हां, स्रोत और प्रलेखन से ऐसा लगता है कि वे एक जैसे हैं, लेकिन वास्तव में System.gc()मेरे लिए काम नहीं Runtime.getRuntime().gc()करता है लेकिन करता है!
इवान

7

मेरा ऐप बहुत सारी छवियों का प्रबंधन करता है और यह एक आउटऑफमेमोरी एरर के साथ मर गया। इससे मुझे मदद मिली। Manifest.xml Add में

<application
....
   android:largeHeap="true"> 

9
Google को यह पसंद नहीं है
पेड्रो पाउलो एमोरिम

1
@PedroPauloAmorim क्यों समझा?
मचाडो

2
जब तक आप सुनिश्चित नहीं करते कि आप क्या कर रहे हैं, तब तक बड़े-बड़े प्रयोग न करें। बड़े ढेर का उपयोग करने से गारबेज कलेक्टर बहुत कठिन काम करता है क्योंकि मेमोरी को साफ़ करने से पहले इसे बहुत सारे जंक डेटा के माध्यम से लूप करना पड़ता है।
प्रकाश

7

आम तौर पर बोलते हुए आपको GC.ly को System.gc () के साथ स्पष्ट रूप से नहीं बुलाना चाहिए। यहां तक ​​कि IO व्याख्यान भी है ( http://www.youtube.com/watch?v=_CruQY55HOk ) जहां वे समझाते हैं कि GC पॉज़ लॉग का क्या अर्थ है और जिसमें वे भी कहते हैं कि कभी भी System.gc () को कॉल न करें क्योंकि Dalvik बेहतर जानते हैं आप से जब ऐसा करने के लिए।

दूसरी ओर जैसा कि ऊपर दिए गए जवाबों में बताया गया है कि एंड्रॉइड में पहले से ही जीसी प्रक्रिया (हर चीज की तरह) कभी-कभी छोटी होती है। इसका मतलब है कि Dalvik GC एल्गोरिदम हॉटस्पॉट या JRockit JVMs के बराबर नहीं है और कुछ मौकों पर गलत हो सकता है। उन अवसरों में से एक है जब बिटमैप ऑब्जेक्ट्स का आवंटन किया जाता है। यह एक मुश्किल है क्योंकि यह हीप और नॉन हीप मेमोरी का उपयोग करता है और क्योंकि मेमोरी की कमी वाले डिवाइस पर बिटमैप ऑब्जेक्ट का एक ढीला उदाहरण आपको आउटऑफमेरी अपवाद देने के लिए पर्याप्त है। इसलिए इसे कॉल करने के बाद आपको इस बिटमैप की आवश्यकता नहीं है, आमतौर पर कई डेवलपर्स द्वारा सुझाव दिया जाता है और कुछ लोगों द्वारा इसे अच्छा अभ्यास भी माना जाता है।

बेहतर व्यवहार एक बिटमैप पर .recycle () का उपयोग कर रहा है क्योंकि यह वही तरीका है जिसके लिए इसे बनाया गया है, क्योंकि यह बिटमैप की मूल मेमोरी को हटाने के लिए सुरक्षित है। ध्यान रखें कि यह बहुत ही संस्करण पर निर्भर है, जिसका अर्थ है कि यह आम तौर पर पुराने एंड्रॉइड संस्करणों (पूर्व 3.0 मुझे लगता है) पर आवश्यक होगा लेकिन बाद के लोगों पर आवश्यक नहीं होगा। इसके अलावा यह नए संस्करणों ईथर (बस एक पाश या ऐसा कुछ में ऐसा नहीं करते) पर इसका उपयोग करने से बहुत चोट नहीं पहुंचेगी। नए एआरटी रनटाइम ने यहां बहुत कुछ बदल दिया क्योंकि उन्होंने बड़ी वस्तुओं के लिए विशेष हीप "विभाजन" की शुरुआत की, लेकिन मुझे लगता है कि एआरटी ईथर के साथ ऐसा करने के लिए बहुत चोट नहीं पहुंचेगी।

साथ ही System.gc () के बारे में एक बहुत ही महत्वपूर्ण नोट। यह विधि एक आदेश नहीं है कि Dalvik (या JVM) जवाब देने के लिए बाध्य हो। वर्चुअल मशीन से यह कहना अधिक पसंद करें कि "क्या आप कचरा संग्रह कर सकते हैं यदि यह कोई परेशानी नहीं है"।



3

मैं नहीं कहूंगा, क्योंकि डेवलपर RAM उपयोग स्थिति पर डॉक्स :

...
GC_EXPLICIT

एक स्पष्ट जीसी, जैसे कि जब आप जीसी कहते हैं () (जिसे आपको कॉल करने से बचना चाहिए और इसके बजाय जीसी पर भरोसा करना चाहिए जब जरूरत हो)।

...

मैंने संबंधित भाग को बोल्ड में हाइलाइट किया है।

यूट्यूब श्रृंखला पर एक नज़र डालें, एंड्रॉयड प्रदर्शन पैटर्न - यह आप अपने ऐप के स्मृति उपयोग के प्रबंधन पर सुझाव दिखाने (जैसे का उपयोग कर Android के रूप में होगा ArrayMapऔर SparseArrayके बजाय एस HashMapरों)।


3

Xamarin डेवलपर्स के लिए त्वरित नोट ।

यदि आप System.gc()Xamarin में कॉल करना चाहते हैं। और ऐप को आपको कॉल करना चाहिएJava.Lang.JavaSystem.Gc()


2

कचरा बीनने वाले को कॉल करने की कोई आवश्यकता नहीं है OutOfMemoryError

यह जावदोक स्पष्ट रूप से बताता है:

Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector.

इसलिए, कचरा इकट्ठा करने वाले ने त्रुटि उत्पन्न करने से पहले ही मेमोरी को खाली करने की कोशिश की, लेकिन असफल रहा।


8
Android Javadoc यह नहीं बताता है, और सबसे अधिक संभावना है कि इसका कार्यान्वयन अलग है। d.android.com/reference/java/lang/OutOfMemoryError.html
hpique

आप सही हैं कि यह Android पर लागू नहीं होता है। लेकिन तब आप फिर से रन ईथर पर OOE को संभाल नहीं सकते हैं, तो आप इसके बारे में बहुत कुछ नहीं कर सकते भले ही यह सच नहीं था।
इगोर :09ordaš
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.