2016-05-03 4 views
17

लटक रहा है मुझे एंड्रॉइड ऐप में वास्तव में अजीब समस्या है। एक निश्चित बिंदु के बाद (जब मुख्य गतिविधि शुरू होती है और एक टुकड़ा प्रदर्शित होता है) FinalizerDememon बस प्रसंस्करण वस्तुओं को रोकता है और कचरा पिलिंग रहता है। एक धागा डंप को देखते हुए, यह ReferenceQueue.remove() पर अटक किया जा रहा है:एंड्रॉइड फ़ाइनलाइज़र डेमॉन

"[email protected]" daemon prio=5 waiting 
    java.lang.Thread.State: WAITING 
     at java.lang.Object.wait(Object.java:-1) 
     at java.lang.Object.wait(Object.java:423) 
     at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:101) 
     - locked <0x1173> (a java.lang.ref.ReferenceQueue) 
     at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:72) 
     at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:185) 
     at java.lang.Thread.run(Thread.java:818) 

अभी तक कतार खाली नहीं है। यदि मैं थोड़ी देर के लिए ऐप का उपयोग करने के बाद ढेर को डंप करता हूं, तो कतार सचमुच हजारों प्रविष्टियां लंबी होती है। डेटा संरचना भी टूटी नहीं दिखती है: FinalizerDaemon instance showing a non-empty ReferenceQueue

आवंटन और कचरा इकट्ठा करने के बाद फिर से डंपिंग कुछ और दिखाता है कि कतार का सिर पहले जैसा ही मैट्रिक्स उदाहरण है।

अब, मैंने यह देखा क्योंकि मैं कुछ सी ++ ऑब्जेक्ट्स को बरकरार रख रहा हूं, जिसे किसी बिंदु पर रिलीज़ करने की आवश्यकता है। जबकि मुझे संदेह है कि जेएनआई कार्यों में कॉल करने वाला एक फाइनलर और सी ++ पक्ष पर कुछ बेवकूफ कर रहा है, तो इसे किसी भी तरह से तोड़ सकता है, मेरे सभी लॉग इंगित करते हैं कि सभी फाइनलर ठीक चल रहे हैं और कुछ भी फेंकने के बिना वापस लौट रहे हैं जब तक कि वे यादृच्छिक रूप से कॉल नहीं हो जाते। साथ ही, डेमॉन को तोड़ने के लिए अंतिम कॉल के लिए वास्तव में संभव नहीं होना चाहिए, पूरे ऐप या कुछ को सीगफॉल्ट करने से कम, क्योंकि वॉचडॉग को फाइनलरों को संभालने वाला माना जाता है जो बहुत लंबे समय तक चलते हैं और अपवाद फेंकते हैं।

मैंने एक स्पष्ट System.runFinalization() की कोशिश की और यह सब हमेशा के लिए मुख्य धागा लटका है, जो डेमॉन की प्रतीक्षा नहीं करता है।

कोई विचार यह कैसे हो सकता है?

+0

https://android.googlesource.com/platform/libcore/+/marshmallow-mr1-release/luni/src/main/java/java/lang/ref/ReferenceQueue.java पर देखकर, यह हमेशा के लिए कुछ इंतजार कर रहा है हटाना। मान लीजिए कि यह यहां फंस गया है (बनाम बहुत जल्दी चल रहा है और आप इसे यहां पकड़ने के लिए होते हैं), जो सुझाव देगा कि नए संदर्भ जोड़े नहीं जा रहे हैं। यदि आप उस कतार पर 'हेड! = नल' देखते हैं, तो ऐसा लगता है कि जो भी जीसी संदर्भ जोड़ने के लिए कर रहा है वह कतार को सिग्नल करने में असफल रहा है। एंड्रॉइड का क्या संस्करण? – fadden

+0

@fadden मैंने प्रश्न संपादित किया। बार-बार ढेर डंप लेते हुए पता चलता है कि कतार का सिर शून्य नहीं है और यह एक ही वस्तु से नहीं चलता है। अंतिम रूप में मेरे लॉग में से कोई भी बिंदु उस बिंदु के बाद प्रिंट नहीं करता है जब यह अटक जाता है। यह बहुत संभावना नहीं है कि ऐप के विभिन्न हिस्सों और विभिन्न उपकरणों पर, हर बार जब मैं कोशिश करता हूं, तो मैं इसे यादृच्छिक रूप से पकड़ता हूं। मैंने इसे नेक्सस 4 (5.1) और एक x86 6.0 एमुलेटर पर पुन: उत्पन्न किया है, और मेरे पास संदेह करने का कारण है कि यह एक दर्जन अन्य परीक्षण उपकरणों पर होता है जो मुझे अभी तक मेरे एंड्रॉइड स्टूडियो से कनेक्ट करने के लिए नहीं मिला है। – IvoDankolov

+0

यह निश्चित रूप से संदर्भक्यू की तरह लगता है सही ढंग से व्यवहार नहीं कर रहा है। या तो यह एक व्यापक समस्या है कि कोई भी नोटिस (संभावना नहीं) के साथ हुआ है, या आपके ऐप ने अनजाने में चीजों को उलझा दिया है। हो सकता है कि कुछ मूल कोड ऑब्जेक्ट सीमाओं के बाहर लिखा और मॉनिटर लॉक को मिटा दिया, तो 'सूचित करें)) अब काम नहीं करता है? जब आप वर्तमान प्रविष्टि को छोड़ते हैं तो यह एक डीबगर को जोड़ने और मैन्युअल रूप से 'हेड' को साफ़ करने या साफ़ करने का प्रयास कर सकता है (और फिर कतार को सिग्नल करने के लिए कुछ और कचरा बना सकता है)। – fadden

उत्तर

1

मुझे विश्वास है कि इसे कुछ अंतिम वस्तुओं के साथ resurrected उनके अंतिम तरीकों से करना है।

मैं इस question से एक अनुच्छेद उद्धृत करूंगा।

फ़ाइनलाइज़र थ्रेड चलता है ताकि कचरा संग्रह किसी ऑब्जेक्ट से जुड़े संसाधनों को साफ़ करने के लिए संचालित हो। यदि मैं इसे मूल रूप से देख रहा हूं, फ़ाइनलाइज़र इस ऑब्जेक्ट को लॉक नहीं प्राप्त कर सकता है: java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:118) क्योंकि जावा ऑब्जेक्ट एक विधि चला रहा है, इसलिए फाइनलज़र थ्रेड लॉक है जब तक कि ऑब्जेक्ट इसके वर्तमान कार्य के साथ समाप्त नहीं हो जाता है।

शायद यह आपके पास है।

+0

मुझे डर है कि यह मामला नहीं है। थ्रेडडंप का कहना है कि केवल FinalizerDememon किसी ऑब्जेक्ट को संदर्भक्यू पर उपलब्ध होने के लिए हमेशा के लिए प्रतीक्षा कर रहा है। लेकिन इसमें कोई वस्तु क्यों नहीं आ रही है? –

+0

यदि आप सही हैं और मैं कुछ दिख रहा हूं: क्या आप बता सकते हैं कि कौन सा जावा ऑब्जेक्ट एक विधि चला रहा है जो फ़ाइनलज़र को लॉक करता है? –

+0

यहां एक थ्रेडम्प है: https://code.google.com/p/android/issues/attachmentText?id=215906&aid=2159060001000&name=threads_report.txt&token=ABZ6GAf2Zh1q6ogUdf33PqBXMILxOHjAjA%3A1469110397989 –

संबंधित मुद्दे