2011-11-02 15 views
5

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

लंबे समय तक मैं सोच रहा था: यदि मैं सेवा में एक नया कॉलबैक ऑब्जेक्ट पास करता हूं और मैं अपनी गतिविधि में कॉलबैक ऑब्जेक्ट में पॉइंटर नहीं रखता हूं तो कचरा कलेक्टर अभी आगे क्यों नहीं जाता है और एकत्र नहीं करता है मेरी गतिविधि प्रक्रिया में कॉलबैक? ऐसा लगता है कि ऐसा नहीं लगता है, JVM कैसे जानता है कि कचरा कब मेरी गतिविधि में कॉलबैक एकत्र करता है।

मुझे लगता है कि जवाब यह है कि बाइंडर सिस्टम गतिविधि प्रक्रिया में मेरे कॉलबैक में एक सूचक रहता है जब तक कि सेवा प्रक्रिया में संबंधित कॉलबैक ऑब्जेक्ट को अंतिम रूप() विधि कहा जाता है, जो तब रिलीज करने के लिए गतिविधि को संदेश भेजता है सूचक क्या यह सही है? यदि नहीं, तो यह कैसे काम करता है?

मेरा मानना ​​है कि यह है और यह दिलचस्प स्थिति की ओर जाता है, जहां गतिविधि में कॉलबैक कुछ स्मृति को गहन करने के लिए इंगित कर रहा है, तब तक इसे एकत्र नहीं किया जाएगा जब तक कि सेवा में कॉलबैक एकत्र नहीं किया जाता है। यदि सेवा मेमोरी पर कम नहीं है तो यह लंबे समय तक कॉलबैक एकत्र नहीं कर सकती है और गतिविधि में आउटऑफमेमरी एरर होने तक कॉलबैक केवल गतिविधि में बन सकता है।

उत्तर

6

युरी काफी सही है।

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

हालांकि गतिविधि में कॉलबैक ऑब्जेक्ट को एंड्रॉइड की बाइंडर सिस्टम द्वारा इंगित किया जाएगा जब तक सेवा में संबंधित कॉलबैक ऑब्जेक्ट कचरा एकत्र नहीं किया जाता है।

यदि गतिविधि प्रक्रिया में कॉलबैक ऑब्जेक्ट कुछ अन्य ऑब्जेक्ट्स पर हावी है जो बहुत सारी मेमोरी का उपभोग करते हैं तो मैं अपनी गतिविधि प्रक्रिया में स्मृति को बर्बाद कर रहा हूं और बिना किसी अच्छे कारण के आउटपुट कर सकता हूं और आउटऑफमेमरी एरर भी प्राप्त कर सकता हूं। समाधान कॉलबैक के साथ किए जाने पर उस कॉल को कॉल करने के लिए destory() नामक कॉलबैक क्लास में एक साधारण विधि बनाना है।

तो कॉलबैक वर्ग एक गैर स्थिर भीतरी वर्ग आप एक स्थिर भीतरी वर्ग के लिए यह बदल रहा है और निर्माता में माता पिता के वर्ग में गुजर विचार कर सकते हैं, इस तरह से आप के साथ-साथ कि बाहर शून्य कर सकते हैं destory() में है तरीका।

यह एक दिलचस्प विचार लाता है, यदि एक गैर स्थैतिक आंतरिक कॉलबैक कक्षा का अभिभावक वर्ग एक गतिविधि है और कॉलबैक के माध्यम से कॉलबैक भेजे जाने के बाद कॉन्फ़िगरेशन परिवर्तन होता है (जैसे स्क्रीन रोटेशन) लेकिन इससे पहले वापस कॉल किया जाता है तो कॉलबैक निष्पादित होने पर पुरानी गतिविधि ऑब्जेक्ट पर इंगित करेगा!

अद्यतन: मैंने इस कोड को Binder.java के अंदर खोजा है, बेशक यह अक्षम है लेकिन अगर वे जावाडॉक्स में इस तरह के सामान का उल्लेख करते हैं तो यह अच्छा होगा।

if (FIND_POTENTIAL_LEAKS) { 
     final Class<? extends Binder> klass = getClass(); 
     if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && 
       (klass.getModifiers() & Modifier.STATIC) == 0) { 
      Log.w(TAG, "The following Binder class should be static or leaks might occur: " + 
       klass.getCanonicalName()); 
     } 
    } 
1

यदि मैं सही ढंग से समझता हूं कि बाइंडर आपके मामले में समस्या का समाधान कैसे करता है तो निम्न है। प्रत्येक इनकमिंग इनकमिंग कॉल के लिए आपकी सेवा एक अलग थ्रेड बनाती है। जब आप इस धागे पर ऑब्जेक्ट पास करते हैं तो आपके बाइंडर सिस्टम थ्रेड के लिए आपकी ऑब्जेक्ट की स्थानीय प्रति बनाता है। इस प्रकार, जब तक आपकी सेवा विधि वापस नहीं आती है परिणामस्वरूप ऑब्जेक्ट की प्रतिलिपि के साथ धागा काम करता रहता है।

यह जांचने के लिए बस अपनी सेवा प्रक्रिया (डीडीएमएस में) के धागे को देखने का प्रयास करें।