स्मृति / संसाधन लीक को खोजने के लिए एंड्रॉइड टूल और तरीके सबसे अच्छा काम करते हैं? [बन्द है]


152

मुझे एक एंड्रॉइड ऐप विकसित किया गया है, और मैं एक फोन ऐप डेवलपमेंट के बिंदु पर हूं जहां सब कुछ अच्छा काम कर रहा है और आप जीत और जहाज की घोषणा करना चाहते हैं, लेकिन आप जानते हैं कि बस कुछ मेमोरी और रिसोर्स लीक होना चाहिए वहाँ पर; और एंड्रॉइड पर केवल 16mb का ढेर है और इसका स्पष्ट रूप से एंड्रॉइड ऐप में लीक होना आश्चर्यजनक रूप से आसान है।

मैं चारों ओर देख रहा हूं और अब तक केवल 'hprof' और 'ट्रेसव्यू' के बारे में जानकारी खोदने में सक्षम रहा हूं और न ही इसे बहुत अधिक अनुकूल समीक्षाएँ मिली हैं।

ओएस परियोजना में साझा करने के लिए आपके पास कौन से उपकरण या विधियां विकसित हुई हैं या विकसित हुई हैं और साझा करने की परवाह है?


3
क्या मैं वोट कर सकता हूं कि कृष्ण ने अपना नाम कुछ मानव पठनीय में बदल दिया।
जेपीएम

1
यदि हम "एंड्रॉइड टूल्स" शब्द को प्रश्न-शीर्षक से हटा दें, तो इस सवाल को फिर से खोलना ठीक होगा? मेरी मेमोरी लीक की समस्याओं को हल करने के लिए यहाँ पाए गए उत्तर काफी उपयोगी थे
k3b

ठीक है, इसलिए मेरे पास एक उपयोगकर्ता लगातार गतिविधियों के बीच स्विच कर रहा है, जिसका अर्थ है कि उन्होंने 20 सेकंड में 15 गतिविधियों को बंद कर दिया है। क्या यह मेमोरी त्रुटि का एक कारण हो सकता है? इसे ठीक करने के लिए मुझे क्या करना चाहिए? धन्यवाद!
रुचिर बरोनिया

1
यह एक प्रतिक्रिया के रूप में प्रदान नहीं कर सकता क्योंकि प्रश्न को बंद कर दिया गया है, हालांकि मैं लीक कैनरी पर एक नज़र डालने की सलाह दूंगा । बस अपने ऐप का उपयोग करें, गतिविधियों को खोलें और बंद करें और लाइब्रेरी को काम करने दें। यह आपको यह भी बताएगा कि रिसाव कहां हुआ था। रिसाव लीक होने के बाद अपना काम करने के लिए बस रिसाव विश्लेषक को कुछ समय दें - यह आमतौर पर लगभग 2 मिनट या उससे अधिक समय लेता है जब तक कि रिसाव का स्रोत नहीं मिला है। इसके बाद यह इसे बड़े करीने से ऐप में पेश करेगा। कोई अतिरिक्त उपकरण की जरूरत है!
ubuntudroid

जवाबों:


90

सबसे आम त्रुटियों में से जो मुझे एंड्रॉइड ऐप विकसित करने में मिली, वह है "java.lang.OutOfMemoryError: बिटमैप का आकार VM बजट से अधिक" त्रुटि। मुझे यह त्रुटि मिली थी कि उन्मुखीकरण बदलने के बाद बहुत सारे बिटमैप्स का उपयोग करने वाली गतिविधियों पर: गतिविधि को नष्ट कर दिया गया है, फिर से बनाया गया है और एक्सएमएल से बिटमैप्स के लिए वीएम मेमोरी का उपभोग करने वाली एक्सफ़ोलिएट को "फुलाया" गया है।

पिछली गतिविधि लेआउट पर बिटमैप्स को कचरा कलेक्टर द्वारा ठीक से निपटाया नहीं गया है क्योंकि उन्होंने अपनी गतिविधि के संदर्भ को पार कर लिया है। कई प्रयोगों के बाद मुझे इस समस्या का काफी अच्छा समाधान मिला।

सबसे पहले, अपने XML लेआउट के मूल दृश्य पर "आईडी" विशेषता सेट करें:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:id="@+id/RootView"
     >
     ...

फिर, अपनी गतिविधि के onDestroy () विधि पर, unbindDrawables () विधि को पेरेंट व्यू के लिए रिफेंस पास करने के लिए कॉल करें और फिर एक System.gc () करें

@Override
protected void onDestroy() {
    super.onDestroy();

    unbindDrawables(findViewById(R.id.RootView));
    System.gc();
}


private void unbindDrawables(View view) {

    if (view.getBackground() != null) {
        view.getBackground().setCallback(null);
    }

    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            unbindDrawables(((ViewGroup) view).getChildAt(i));
        }

        ((ViewGroup) view).removeAllViews();
    }
}

इस unbindDrawables () विधि दृश्य पेड़ की पुनरावृत्ति और:

  1. सभी बैकग्राउंड ड्रॉबल्स पर कॉलबैक को हटाता है
  2. हर व्यूग्रुप पर चिल्ड को हटाता है

3
एक आम समस्या का अच्छा समाधान।
E

9
यह AdapterView (ListView, GridView आदि) के उपवर्गों के लिए काम नहीं करता है।
अर्जुन

@ अर्जुन हां..यह एडॉप्टर व्यू उपवर्गों के लिए काम नहीं करता है। इसके लिए आपको अपवाद को संभालने की आवश्यकता है। बाकी यह ठीक काम करता है। यही मैं अपने कोड में उपयोग करता हूं और यह ठीक काम करता है। उम्मीद है की यह मदद करेगा।
hp.android

@ hp.android "अपवाद में इसे संभालें" क्या आपके पास इसका उदाहरण है कि यह कैसा दिखेगा? मैं पूछता हूं क्योंकि मेरे पास छवियों के पृष्ठ हैं PageAdapterऔर मैं इस त्रुटि से काम कर रहा हूं :(
जैक्सनक्रा

4
@ जैकसन केवल स्थिति को बदल देता है: यदि (देखें उदाहरण देखें ViewGroup &&! (देखें instof AdapterView)) इससे आपको अपवाद से छुटकारा मिल जाएगा जो आपको एडाप्टर के लिए मिल रहा है
hp.android


28

अधिकतर भविष्य के Google यात्रियों के लिए:

अधिकांश जावा उपकरण दुर्भाग्य से इस कार्य के लिए अनुपयुक्त हैं, क्योंकि वे केवल जेवीएम-हीप का विश्लेषण करते हैं। हर एंड्रॉइड एप्लिकेशन में एक देशी ढेर भी होता है, हालांकि, इसे ~ 16 एमबी की सीमा के भीतर भी फिट करना पड़ता है। यह आमतौर पर बिटमैप डेटा के लिए उपयोग किया जाता है, उदाहरण के लिए। तो आप बहुत आसानी से आउट ऑफ मेमोरी त्रुटियों में भाग सकते हैं, भले ही आपका जेवीएम-हीप 3 एमबी के आसपास चिलिन हो, अगर आप बहुत सारे ड्रॉबल्स का उपयोग करते हैं।


6
एंड्रॉइड 3.0 (हनीकॉम्ब)
ड्रॉबल्स

@ तोमो आप देशी हीप में लीक का पता लगाने के लिए क्या इस्तेमाल करेंगे?
sydd

1
परीक्षण, परीक्षण के बहुत सारे। समस्या यह है कि आप वास्तव में यह भी नहीं बता सकते कि मेमोरी शेयरिंग और अन्य अनुकूलन तकनीकों के कारण आपका ऐप कितनी मेमोरी का उपयोग कर रहा है। आप सामान्य शेल कमांड का उपयोग करके मेमोरी रीडिंग प्राप्त कर सकते हैं, लेकिन वे बहुत, बहुत मोटे अनुमान हैं।
टिमो ओह्र

20

@ Hp.android से जवाब अच्छी तरह से काम करता है अगर आप सिर्फ बिटमैप पृष्ठभूमि के साथ काम कर रहे हैं, लेकिन मेरे मामले में, मैं एक था BaseAdapterका एक सेट उपलब्ध कराने के ImageViewएक के लिए रों GridView। मैंने unbindDrawables()सलाह के अनुसार विधि को संशोधित किया है ताकि यह शर्त हो:

if (view instanceof ViewGroup && !(view instanceof AdapterView)) {
  ...
}

लेकिन समस्या यह है कि पुनरावर्ती विधि कभी भी बच्चों को संसाधित नहीं करती है AdapterView। इसे संबोधित करने के लिए, मैंने इसके बजाय निम्नलिखित किया:

if (view instanceof ViewGroup) {
  ViewGroup viewGroup = (ViewGroup) view;
  for (int i = 0; i < viewGroup.getChildCount(); i++)
    unbindDrawables(viewGroup.getChildAt(i));

  if (!(view instanceof AdapterView))
    viewGroup.removeAllViews();
}

ताकि बच्चों AdapterViewको अभी भी संसाधित किया जाता है - विधि सिर्फ सभी बच्चों को निकालने का प्रयास नहीं करती है (जो कि असमर्थित है)।

यह समस्या को काफी हद तक ठीक नहीं करता है, क्योंकि ImageViewएक बिटमैप का प्रबंधन होता है जो उनकी पृष्ठभूमि नहीं है। इसलिए मैंने निम्नलिखित जोड़ा है। यह आदर्श नहीं है, लेकिन यह काम करता है:

if (view instanceof ImageView) {
  ImageView imageView = (ImageView) view;
  imageView.setImageBitmap(null);
}

कुल मिलाकर unbindDrawables()विधि तब है:

private void unbindDrawables(View view) {
  if (view.getBackground() != null)
    view.getBackground().setCallback(null);

  if (view instanceof ImageView) {
    ImageView imageView = (ImageView) view;
    imageView.setImageBitmap(null);
  } else if (view instanceof ViewGroup) {
    ViewGroup viewGroup = (ViewGroup) view;
    for (int i = 0; i < viewGroup.getChildCount(); i++)
    unbindDrawables(viewGroup.getChildAt(i));

    if (!(view instanceof AdapterView))
      viewGroup.removeAllViews();
  }
}

मुझे उम्मीद है कि इस तरह के संसाधनों को मुक्त करने के लिए अधिक राजसी दृष्टिकोण है।


12

एंड्रॉइड में मेमोरी मैनेजमेंट पर अच्छा Google I / O टॉक (2011), साथ ही मेमोरी प्रोफाइलिंग के लिए टूल + तकनीक पर विवरण:
http://www.youtube.com/watch?v=_CruQY55HOk


4
या संगत ब्लॉग पोस्ट: android-developers.blogspot.com/2011/03/…
greg7gkb

1
ठीक है, इसलिए मेरे पास एक उपयोगकर्ता लगातार गतिविधियों के बीच स्विच कर रहा है, जिसका अर्थ है कि उन्होंने 20 सेकंड में 15 गतिविधियों को बंद कर दिया है। क्या यह मेमोरी त्रुटि का एक कारण हो सकता है? इसे ठीक करने के लिए मुझे क्या करना चाहिए? धन्यवाद!'
रुचिर बरोनिया

4

Valgrind को Android (मोज़िला द्वारा प्रायोजित) में पोर्ट किया गया है। Android पर Valgrind देखें - ARM पर Android के लिए वर्तमान स्थिति और समर्थन चल रहे Valgrind (टिप्पणी 67)।


इसके लिए कस्टम रोम बनाने की आवश्यकता होगी।
अक्षत

1

खैर, वे उपकरण हैं जो एंड्रॉइड का उपयोग करने वाले अद्वितीय स्वरूपों के साथ हुक करते हैं..मुझे लगता है कि आप जिस चीज से असंतुष्ट हो सकते हैं वह उपयोग में अंतर्निहित परीक्षण कोड फ्रेमवर्क है ..

क्या आपने एंड्रॉइड मॉक फ्रेमवर्क का उपयोग करके कोड के मॉक टेस्टिंग क्षेत्रों की कोशिश की है?


1
ऐसा नहीं है, उस प्रकृति का परीक्षण इतना मुद्दा नहीं है जितना कि रिकॉर्डिंग वास्तव में क्या हो रहा है, जबकि अनुप्रयोग चलता है, मुझे वास्तव में क्या चाहिए एक संसाधन / मेमोरी लीक प्रोफाइलिंग टूल है
jottos
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.