2010-06-14 22 views
34

देख सकता हूं, मेरे पास 600x800 पिक्सेल जेपीईजी से अधिक गैलरी के साथ आउटऑफमेमरी अपवाद है।एंड्रॉइड: आउटफमेमरी एरर: बिटमैप आकार वीएम बजट से अधिक नहीं है, मुझे कोई कारण नहीं है कि मैं


पर्यावरण

मैं गया है 600x800 पिक्सल के आसपास जेपीजी छवियों के साथ गैलरी का उपयोग किया गया।

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

उपयोगकर्ता अनुभव को "तेज़" करने के लिए मेरे पास 4 स्लॉट का एक सरल कैश है जो प्रीफ़ेच (लूपर में) लगभग 1 छवि बाईं ओर और 1 छवि प्रदर्शित छवि पर सही है और उन्हें 4 स्लॉट हैश मैप में रखता है।

मंच

मैं 256 रैम और 128 ढेर आकार की AVD उपयोग कर रहा हूँ, एक 600x800 स्क्रीन के साथ। यह एंटोरेज एज लक्ष्य पर भी होता है, सिवाय इसके कि डिवाइस के साथ डीबग करना कठिन होता है।


समस्या

मैं एक अपवाद हो रही किया गया है:

OutofMemoryError: bitmap size exceeds VM budget 

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


अजीब बात:

आदेश यकीन है कि ढेर सीमा बहुत दूर मैं क्या जरूरत से दूर है बनाने के लिए, मैं में एक डमी 8MB सरणी को परिभाषित किया है वहाँ एक स्मृति समस्या नहीं किया जाना चाहिए शुरुआत, और इसे बिना संदर्भित छोड़ दिया ताकि इसे तुरंत प्रेषित किया जा सके। यह गतिविधि धागा के एक सदस्य है और

static { @SuppressWarnings("unused") 
byte dummy[] = new byte[ 8*1024*1024 ]; }  

नतीजा यह है कि ढेर आकार लगभग 11MB है और यह सब मुफ़्त है है निम्नलिखित के रूप में परिभाषित किया गया है। नोट मैंने क्रैश होने के बाद उस चाल को जोड़ा है। यह आउटऑफमेमरी कम बार-बार बनाता है।

अब, मैं डीडीएमएस का उपयोग कर रहा हूं। बस से पहले दुर्घटना (दुर्घटना के बाद ज्यादा परिवर्तन नहीं करता है), डी डी एम एस पता चलता है:

ID Heap Size Allocated Free  %Used #Objects 
1 11.195 MB 2.428 MB 8.767 MB 21.69% 47,156 

और विस्तार तालिका में दिखाई देता है:

Type Count Total Size Smallest Largest Median Average 
free 1,536 8.739MB  16B  7.750MB 24B  5.825KB 

सबसे बड़ा ब्लॉक 7.7MB है। और फिर भी LogCat का कहना है:

ERROR/dalvikvm-heap(1923): 925200-byte external allocation too large for this process. 

आप मंझला और औसत के संबंध मन है, तो यह मान लेना कि उपलब्ध ब्लॉक के सबसे बहुत छोटे होते हैं प्रशंसनीय है। हालांकि, बिटमैप के लिए काफी बड़ा ब्लॉक है, यह 7.7 एम है। यह अभी भी पर्याप्त नहीं है?

नोट: मैंने एक ढेर का निशान दर्ज किया। आवंटित डेटा की मात्रा को देखते समय, ऐसा लगता है कि 2 एम से अधिक आवंटित नहीं किया गया है। यह डीडीएमएस द्वारा मुफ्त मेमोरी रिपोर्ट से मेल खाता है।


  • यह हो सकता है कि मैं ढेर-विखंडन जैसे कुछ समस्या का अनुभव?
  • मैं समस्या को हल/हल कैसे करूं?
  • क्या ढेर सभी धागे से साझा किया जाता है?
  • क्या यह हो सकता है कि मैं गलत तरीके से डीडीएमएस रीडआउट की व्याख्या करता हूं, और आवंटित करने के लिए वास्तव में कोई 900 के ब्लॉक नहीं है? यदि हां, तो क्या कोई मुझे बता सकता है कि मैं उसे कहां देख सकता हूं?

धन्यवाद एक बहुत

Meymann

+0

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

+0

कोड डीबग करते समय, मेरा मुख्य संदिग्ध हमेशा मेरा कोड होता है। इसे डीबग करने के लिए, मुझे पर्यावरण से संकेत प्राप्त होते हैं। दुर्भाग्यवश, इस मामले में: ए एक साधारण कोड बना रहा है जो कैश में एक समय में 600x800 की 3 छवियों को पढ़ता है, इसी तरह के परिणाम स्पोरैडिक रूप से उत्पन्न करेगा (चेक किया गया है ताकि इसे तेज़ी से तेज किया जा सके, कोई डमी असुरक्षित सरणी जोड़ सकता है) बी। मैं समस्या की जांच करने के लिए उपकरण का उपयोग करता हूं, लेकिन उपकरण से मिलने वाले संकेत मेल नहीं खाते हैं। सी। इस प्रश्न का बिंदु क्या अच्छा अभ्यास है, डीडीएमएस रीडआउट के बारे में मेरे निष्कर्षों में क्या गलत है, और यदि कोई कामकाज है तो संकेत मिल रहा है। – Meymann

+1

** किसी अन्य रूप में समस्या को पुन: उत्पन्न करने का एक बहुत ही आसान तरीका ** 1. अपनी गतिविधि कक्षा में, स्थिर {बाइट डमी [] = नया बाइट [4096] जोड़ें; } विस्तार करने के लिए ढेर को मजबूर करने के लिए (और संदेह को हटा दें)। 2. एक व्यूफ्लिपर बनाएं। 3. लगभग 10 छवि दृश्य जोड़ें जहां प्रत्येक 600x800 बिटमैप को संदर्भित करता है। 4. जब यह दुर्घटनाग्रस्त हो जाता है, तो डीडीएमएस देखें। – Meymann

उत्तर

12

मुझे लगता है कि आपके मामले में कुछ खास नहीं है। बस पर्याप्त स्मृति नहीं है। स्मृति में आपके पास 600x800 बिटमैप नहीं हो सकते हैं, वे बहुत अधिक स्मृति का उपभोग करते हैं। आपको उन्हें एसडी में सहेजना चाहिए और मांग पर स्मृति में लोड करना चाहिए। मुझे लगता है कि यह वही है जो आप करते हैं।

एक चीज आपको इसके बारे में पता होना चाहिए: डीडीएमएस जावा हीप मेमोरी खपत प्रदर्शित करता है। लेकिन मूल स्मृति भी है जो डीडीएमएस में प्रदर्शित नहीं होती है। और जहां तक ​​मैं समझता हूं बिटमैप्स देशी स्मृति में बनाए जाते हैं। तो डीडीएमएस इन स्मृति मुद्दों को ट्रैक करने के लिए सिर्फ एक बुरा उपकरण है। आपको बस यह सुनिश्चित करने की ज़रूरत है कि आप अपनी याददाश्त मुक्त करें, कि छवियों को कचरा कलेक्टर द्वारा एकत्रित किया जाता है जब आपको उनकी आवश्यकता नहीं होती है।

कचरा कलेक्टर अपने स्वयं के कार्यक्रम पर काम करता है। यही कारण है कि आपको बिटमैप पर Bitmap.recycle() विधि को कॉल करना चाहिए जिसे आपको अब और आवश्यकता नहीं है। यह विधि वास्तव में उस मूल स्मृति को मुक्त करती है जिसे आप समाप्त करते हैं। इस तरह आप जीसी पर निर्भर नहीं हैं और आप जितनी जल्दी हो सके स्मृति का सबसे बड़ा टुकड़ा मुक्त कर सकते हैं।

सबसे पहले आपको यह सुनिश्चित करना चाहिए कि आप बिटमैप्स को रिसाव न करें।

यहाँ एक अच्छा post स्मृति आवंटन पर यह आप खुदाई करने के लिए मैं इसके अलावा सप्ताह के समान मुद्दा जोड़ी वापस सामना करना पड़ा गहरी

+0

निश्चित रूप से, एसडी से आलसी लोडिंग वह है जो मैं कर रहा हूं। गैलरी क्या कर रही है। मैं इसे गति देने के लिए 4-स्लॉट कैश का उपयोग कर रहा हूं, हालांकि। फिर भी, मुझे समझने की 3 चीजें हैं: 1. मैं अप्रयुक्त छवियों को प्रेषित करने के लिए गैलरी को कैसे मजबूर करूं? 2. यह कैसे पर्याप्त नहीं है? 800x600x4imagesx3bytesPerPixel = 5M जो 16 एम से छोटा है। 3. मुझे आश्चर्य है कि यह इतना स्पोराडिक क्यों है। कभी-कभी यह काम करता है, और यह हर समय विभिन्न स्थानों पर उड़ता है। धन्यवाद – Meymann

+3

जब आप 4-स्लॉट कैश का उपयोग करते हैं तो आप रीसायकल() को कॉल कर सकते हैं जब आप इस कैश से पुरानी छवि हटा रहे हैं। – Fedor

+1

जब एडाप्टर कन्वर्ट व्यू में getView को बुलाया जाता है तो आपको पास कर दिया जाता है। दरअसल यह एक ऐसा विचार है जिसे पुनर्नवीनीकरण किया जा रहा है। इस दृश्य पर प्रदर्शित बिटमैप उदाहरण की आवश्यकता नहीं है। तो मुझे लगता है कि आप उस छवि दृश्य पर प्रदर्शित बिटमैप कर सकते हैं और इसे रीसायकल कर सकते हैं। यह ASAP दृष्टिकोण के करीब कुछ है। – Fedor

5
नहीं

यकीन है कि अगर यह आप के लिए एक विकल्प है, लेकिन आप supersampling की कोशिश की है छवियों Strange out of memory issue while loading an image to a Bitmap object?

+1

धन्यवाद, लेकिन मुझे डर है कि यह नहीं करेगा ... यह छवि की गुणवत्ता को मारता है, क्योंकि यह डिकोडर को अधिक "मैला" होने की अनुमति देता है। नतीजतन, छवि के पाठ और छोटे टुकड़े बहुत smeared हो जाते हैं ... जेपीईजी की तरह जानता है कि कैसे धुंधला है ... यह वास्तव में जेपीईजी EXIF ​​थंबनेल लेने और इसे पूर्ण पैमाने पर आकार बदलने के दौरान क्या होता है जैसा दिखता है। धन्यवाद – Meymann

0

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

0

मैंने उससे पूछा कि बहुत समय हो गया है।

उत्तर 2 भागों में विभाजित किया जाना चाहिए: प्री-जिंजरब्रेड: आप बस छोटी तस्वीरों का उपयोग करें, सबसमलिंग का उपयोग करें, शायद एक स्क्रीन आकार की फोटो, और अच्छे के लिए आशा करें। यह सुनिश्चित करने का प्रयास करें कि आप छोटे आइटम आवंटित नहीं करते हैं जिन्हें आप बिटमैप प्राप्त करने से पहले मुक्त नहीं कर सकते हैं। प्री-अदरक, बीएमपीएस के लिए स्मृति को अव्यवस्थित होना था, और इसे वीएम मेमोरी में गिना नहीं गया था। हमेशा लॉगकैट देखें। Google IO 2011 से स्मृति के बारे में एक व्याख्यान देखें। पोस्ट अदरक यह आसान है। हनीकॉम्ब के बाद से, आपके जावा क्षेत्र में बिटमैप्स भी गिना जाता है। कोई जेनी क्षेत्र नहीं है। हमेशा बिटमैप्स के लिए रीसायकल का उपयोग करें जिसकी आपको आवश्यकता नहीं है। जीसी के लिए इंतजार मत करो।

0

प्रश्न 2010 में पूछा गया था, जब फियोयो ताजा था। तब से कई चीजें हुईं। 3.0 से पहले, जेएनआई में बिटमैप्स आवंटित किए गए थे। स्मृति Dalvik आंकड़ों में नहीं दिखाया गया था। अब यह एकान्त नहीं होना चाहिए। 2.3 से पहले, जेएनआई के लिए मेमोरी आंकड़े उपलब्ध नहीं थे (बिटमैप डिकोडिंग जेएनआई को कॉल करता है) लॉगकैट में। 4.4 और अधिक स्थान निकाला गया। 5.0 कला का बड़ा धमाका। 2010 में वापस, नेक्सस वन 300 एमबी से कम के साथ उच्च अंत था। एक ऐप के लिए बजट लगभग 16 एमबी था। अब दिन, स्मृति के बारे में 8 गुना है।