कैसे संभालें: java.util.concurrent.TimeoutException: android.os.BinderProxy.finalize () 10 सेकंड की त्रुटियों के बाद समय समाप्त हो गया?


167

हम की एक संख्या को देख रहे हैं TimeoutExceptionsमें GcWatcher.finalize, BinderProxy.finalize, और PlainSocketImpl.finalize। उनमें से 90 +% एंड्रॉइड 4.3 पर होता है। हम इस क्षेत्र में उपयोगकर्ताओं से Crittercism की रिपोर्ट प्राप्त कर रहे हैं।

यहां छवि विवरण दर्ज करें

त्रुटि का एक रूपांतर है: " com.android.internal.BinderInternal$GcWatcher.finalize() timed out after 10 seconds"

java.util.concurrent.TimeoutException: android.os.BinderProxy.finalize() timed out after 10 seconds
at android.os.BinderProxy.destroy(Native Method)
at android.os.BinderProxy.finalize(Binder.java:459)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:187)
at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:170)
at java.lang.Thread.run(Thread.java:841)

अब तक हमारे पास घर में समस्या को दूर करने या इसका कारण क्या हो सकता है, इसका पता लगाने का कोई सौभाग्य नहीं है।

किसी भी विचार यह क्या कारण हो सकता है? किसी भी विचार यह कैसे डीबग करें और पता करें कि ऐप का कौन सा हिस्सा इसका कारण बनता है? समस्या पर प्रकाश डालने वाली कोई भी चीज़ मदद करती है।

अधिक सामान:

1   android.os.BinderProxy.destroy  
2   android.os.BinderProxy.finalize Binder.java, line 482
3   java.lang.Daemons$FinalizerDaemon.doFinalize    Daemons.java, line 187
4   java.lang.Daemons$FinalizerDaemon.run   Daemons.java, line 170
5   java.lang.Thread.run    Thread.java, line 841  

2

1   java.lang.Object.wait   
2   java.lang.Object.wait   Object.java, line 401
3   java.lang.ref.ReferenceQueue.remove ReferenceQueue.java, line 102
4   java.lang.ref.ReferenceQueue.remove ReferenceQueue.java, line 73
5   java.lang.Daemons$FinalizerDaemon.run   Daemons.java, line 170
6   java.lang.Thread.run

3

1   java.util.HashMap.newKeyIterator    HashMap.java, line 907
2   java.util.HashMap$KeySet.iterator   HashMap.java, line 913
3   java.util.HashSet.iterator  HashSet.java, line 161
4   java.util.concurrent.ThreadPoolExecutor.interruptIdleWorkers    ThreadPoolExecutor.java, line 755
5   java.util.concurrent.ThreadPoolExecutor.interruptIdleWorkers    ThreadPoolExecutor.java, line 778
6   java.util.concurrent.ThreadPoolExecutor.shutdown    ThreadPoolExecutor.java, line 1357
7   java.util.concurrent.ThreadPoolExecutor.finalize    ThreadPoolExecutor.java, line 1443
8   java.lang.Daemons$FinalizerDaemon.doFinalize    Daemons.java, line 187
9   java.lang.Daemons$FinalizerDaemon.run   Daemons.java, line 170
10  java.lang.Thread.run

4

1   com.android.internal.os.BinderInternal$GcWatcher.finalize   BinderInternal.java, line 47
2   java.lang.Daemons$FinalizerDaemon.doFinalize    Daemons.java, line 187
3   java.lang.Daemons$FinalizerDaemon.run   Daemons.java, line 170
4   java.lang.Thread.run

2
कोई बात नहीं, पाया कि यह Bugzilla.mozilla.org/show_bug.cgi?id=864102 मैं भी पुष्टि कर सकता हूं कि हमारे ऐप्स प्रभावित हो रहे हैं, यह Google Play Services के मुद्दे की तरह बदबू आ रही है
eveliotc

कोड की पंक्ति जिसे त्रुटि डाली गई है, संस्करण 4.3_r1 पेश किया गया था, जिसे 5 जून 2013 में जारी किया गया था। हो सकता है कि समस्या तब से हो रही हो।
एडुब्रिगेंटी

एंड्रॉइड वर्जन 4.2.2 ने भी इस अपवाद को फेंकना शुरू कर दिया है, हो सकता है कि इसका एक Google Play अपडेट स्रोत हो।
JWqvist

@EvelioTarazona मेरे पास कुछ ऐप में है जो प्ले-सेवाओं का उपयोग नहीं करता है
ligi

@ लिगी यह आपके लिए समान स्टैक-ट्रेस है?
14

जवाबों:


220

पूर्ण प्रकटीकरण - मैं TLV DroidCon में पहले उल्लेख की गई बात का लेखक हूं।

मेरे पास कई Android अनुप्रयोगों में इस मुद्दे की जांच करने का मौका था, और इसका सामना करने वाले अन्य डेवलपर्स के साथ चर्चा करें - और हम सभी को एक ही बिंदु मिला: इस मुद्दे को टाला नहीं जा सकता, केवल न्यूनतम किया गया।

मैंने एंड्रॉइड गारबेज कलेक्टर कोड के डिफ़ॉल्ट कार्यान्वयन पर बारीकी से विचार किया, यह समझने के लिए कि यह अपवाद क्यों फेंका गया है और इसके संभावित कारण क्या हो सकते हैं। मैंने प्रयोग के दौरान एक संभावित मूल कारण भी पाया।

समस्या की जड़ कुछ समय के लिए एक डिवाइस "गोसे टू स्लीप" है - इसका अर्थ है कि ओएस ने थोड़ी देर के लिए अधिकांश उपयोगकर्ता भूमि प्रक्रियाओं को रोककर और सीपीयू चक्र को कम करते हुए स्क्रीन की बैटरी की खपत को कम करने का फैसला किया है। , आदि जिस तरह से किया जाता है - एक लिनक्स सिस्टम स्तर पर होता है, जहां प्रक्रियाओं को मध्य में रोका जाता है। यह सामान्य अनुप्रयोग निष्पादन के दौरान किसी भी समय हो सकता है, लेकिन यह नेटिव सिस्टम कॉल पर बंद हो जाएगा, क्योंकि संदर्भ स्विच कर्नेल स्तर पर किया जाता है। तो - यह वह जगह है जहाँ Dalvik GC कहानी में शामिल होता है।

Dalvik GC कोड (AOSP साइट में Dalvik परियोजना में लागू किया गया) कोड का एक जटिल टुकड़ा नहीं है। काम करने का मूल तरीका मेरी DroidCon स्लाइड में शामिल है। मैंने जो कवर नहीं किया, वह मूल जीसी लूप है - उस बिंदु पर जहां कलेक्टर के पास अंतिम रूप देने (और नष्ट करने) के लिए वस्तुओं की एक सूची है। आधार पर लूप लॉजिक को इस तरह सरल बनाया जा सकता है:

  1. लेना starting_timestamp,
  2. वस्तुओं की सूची जारी करने के लिए ऑब्जेक्ट निकालें,
  3. रिलीज़ ऑब्जेक्ट - finalize()और destroy()यदि आवश्यक हो तो देशी कॉल करें ,
  4. लेना end_timestamp,
  5. गणना ( end_timestamp - starting_timestamp) और 10 सेकंड के हार्ड कोडित टाइमआउट मूल्य के खिलाफ तुलना करें,
  6. अगर टाइमआउट पहुँच गया है - java.util.concurrent.TimeoutExceptionइस प्रक्रिया को मारें और मारें।

अब इस परिदृश्य पर विचार करें:

आवेदन अपनी बात करने के साथ चलता है।

यह एक उपयोगकर्ता का सामना करने वाला एप्लिकेशन नहीं है, यह पृष्ठभूमि में चलता है।

इस पृष्ठभूमि के संचालन के दौरान, वस्तुओं को बनाया जाता है, उपयोग किया जाता है और स्मृति को जारी करने के लिए एकत्र करने की आवश्यकता होती है।

अनुप्रयोग वेकॉक के साथ परेशान नहीं करता है - क्योंकि इससे बैटरी पर प्रतिकूल प्रभाव पड़ेगा, और यह अनावश्यक लगता है।

इसका मतलब है कि समय-समय पर आवेदन जीसी को लागू करेगा।

आम तौर पर जीसी रन बिना किसी बाधा के पूरा होता है।

कभी-कभी (बहुत कम ही) सिस्टम जीसी रन के बीच में सोने का फैसला करेगा।

यह तब होगा जब आप अपने एप्लिकेशन को लंबे समय तक चलाएंगे, और Dalvik मेमोरी लॉग को बारीकी से मॉनिटर करेंगे।

अब - मूल जीसी लूप के टाइमस्टैम्प तर्क पर विचार करें - डिवाइस को रन शुरू करना, ए लेना start_stamp, और destroy()सिस्टम ऑब्जेक्ट पर मूल कॉल पर सो जाना संभव है ।

जब यह उठता है और रन को फिर से शुरू करता है, तो destroy()इच्छा समाप्त हो जाएगी, और अगली end_stampबार यह destroy()कॉल + नींद का समय होगा।

यदि नींद का समय लंबा था (10 सेकंड से अधिक), तो java.util.concurrent.TimeoutExceptionफेंक दिया जाएगा।

मैंने इसे विश्लेषण अजगर लिपि से उत्पन्न रेखांकन में देखा है - एंड्रॉइड सिस्टम एप्लिकेशन के लिए, न केवल मेरे स्वयं के मॉनिटर किए गए एप्लिकेशन के लिए।

पर्याप्त लॉग एकत्र करें और आप अंततः इसे देखेंगे।

जमीनी स्तर:

इस मुद्दे को टाला नहीं जा सकता - यदि आपका ऐप बैकग्राउंड में चलता है तो आप इसका सामना करेंगे।

आप एक वेकॉक ले कर कम कर सकते हैं, और डिवाइस को सोने से रोक सकते हैं, लेकिन यह पूरी तरह से एक अलग कहानी है, और एक नया सिरदर्द, और शायद एक और चोर में एक और बात है।

आप जीसी कॉल को कम करके समस्या को कम कर सकते हैं - परिदृश्य को कम करने की संभावना (टिप्स स्लाइड में हैं)।

मुझे अभी तक Dalvik 2 (उर्फ ART) GC कोड पर जाने का मौका नहीं मिला है - जो एक नई पीढ़ीगत कॉम्पैक्टिंग सुविधा का दावा करता है, या Android लॉलीपॉप पर कोई प्रयोग करता है।

जोड़ा गया 7/5/2015:

इस क्रैश प्रकार के लिए क्रैश रिपोर्ट एकत्रीकरण की समीक्षा करने के बाद, यह एंड्रॉइड ओएस के संस्करण 5.0+ से इन क्रैशों की तरह दिखता है (एआरटी के साथ लॉलीपॉप) इस दुर्घटना प्रकार का केवल 0.5% है। इसका मतलब यह है कि एआरटी जीसी परिवर्तनों ने इन क्रैश की आवृत्ति को कम कर दिया है।

जोड़ा गया 6/1/2016:

लगता है कि एंड्रॉइड प्रोजेक्ट ने बहुत सी जानकारी जोड़ी है कि जीसी डेल्विक 2.0 (उर्फ एआरटी) में कैसे काम करता है।

आप इसके बारे में यहां पढ़ सकते हैं - डीबगिंग एआरटी कचरा संग्रह

यह आपके ऐप के लिए GC व्यवहार के बारे में जानकारी प्राप्त करने के लिए कुछ टूल पर भी चर्चा करता है।

अपनी एप्लिकेशन प्रक्रिया के लिए एक SIGQUIT भेजना अनिवार्य रूप से एक ANR का कारण होगा, और विश्लेषण के लिए एक लॉग फ़ाइल में एप्लिकेशन स्टेट को डंप कर देगा।


मेरे मामले में, मैं पृष्ठभूमि में चल रहे कोड / समय की मात्रा को कम करने के तरीके ढूंढकर इसे कम करने की कोशिश कर रहा हूं। विषय पर अपने शोध के लिए धन्यवाद।
पार्करफैथ

आपके ऐप में किए गए किसी भी बैकग्राउंड प्रोसेसिंग को हटाने से समस्या को कम करने में बहुत मदद मिलेगी।
ओबा

इसके लायक क्या है, यह मार्शमैलो (6.0.1) में अभी भी होता है। उस ने कहा, मुझे केवल एक बार यह त्रुटि मिली है। तो यह एक भारी समस्या नहीं लगती है। आपके संपूर्ण स्पष्टीकरण के लिए धन्यवाद।
नॉसोस

कुछ समय बाद, मुझे यह स्पष्ट आभास हुआ कि ओएस में इस समस्या को ठीक करना बहुत समस्याग्रस्त है, और इसके लिए Google और ओईएम के बीच सहयोग की आवश्यकता है। मुझे उम्मीद नहीं है कि यह जल्द ही तय हो जाएगा।
ओबा

मैं wakelock का उपयोग कर रहा हूं, लेकिन अभी भी एंड्रॉइड 4.4.2 पर इस मुद्दे का सामना कर रहा हूं। मेरे ऐप में कुछ बैकग्राउंड ऑपरेशंस हैं लेकिन मुख्य रूप से चार्ज केबल माउंट होने के दौरान दिन भर काम करने के लिए डिज़ाइन किया गया है। क्या इस मुद्दे को कम करने का कोई अलग तरीका है?
Orcun Sevsay

74

हम यह लगातार, हमारे ऐप पर क्रैशशीटिक्स का उपयोग करते हुए देखते हैं। प्लेटफॉर्म कोड में क्रैश आमतौर पर होता है। एक छोटा सा नमूना:

android.database.CursorWindow.finalize () 10 सेकंड के बाद समाप्त हो गया

java.util.regex.Matcher.finalize () 10 सेकंड के बाद समय समाप्त हो गया

android.graphics.Bitmap $ BitmapFinalizer.finalize () 10 सेकंड के बाद समाप्त हो गया

org.apache.http.impl.conn.SingleClientConnManager.finalize () 10 सेकंड के बाद समय समाप्त

java.util.concurrent.ThreadPoolExecutor.finalize () 10 सेकंड के बाद समय समाप्त हो गया

android.os.BinderProxy.finalize () 10 सेकंड के बाद समय समाप्त हो गया

android.graphics.Path.finalize () 10 सेकंड के बाद समाप्त हो गया

जिन उपकरणों पर यह होता है, वे सैमसंग द्वारा निर्मित (लेकिन विशेष रूप से नहीं) उपकरण होते हैं। इसका मतलब यह हो सकता है कि हमारे अधिकांश उपयोगकर्ता सैमसंग उपकरणों का उपयोग कर रहे हैं; वैकल्पिक रूप से यह सैमसंग उपकरणों के साथ एक समस्या का संकेत दे सकता है। मैं बहुत पक्का नहीं हूँ।

मुझे लगता है कि यह वास्तव में आपके सवालों का जवाब नहीं देता है, लेकिन मैं सिर्फ यह कहना चाहता हूं कि यह काफी सामान्य है, और आपके आवेदन के लिए विशिष्ट नहीं है।


16
यह एंड्रॉइड 5.0.1 संस्करण के लिए भी हो रहा है और सैमसंग उपकरणों तक सीमित नहीं लगता है। यह नेक्सस 6. पर हुआ
शोभित पुरी

4
मेरे पास यह मुद्दा Android 4.4.4 पर XIAOMI द्वारा निर्मित डिवाइस के साथ है
परेश दुधात

बस इसमें झंकार करना चाहता था कि हम इनमें से अधिकांश दुर्घटनाओं को सैमसंग टैबलेट पर देख रहे हैं। सुनिश्चित नहीं है कि सैमसंग ने अलग-अलग तरीके से कैसे किया कि टैबलेट पृष्ठभूमि वाले ऐप को कैसे संभालते हैं।
FriendlyMikhail

1
मैं एंड्रॉयड 4.4.4 पर इस मुद्दे को है। डिवाइस HUAWEI द्वारा निर्मित।
रमेशबाबू

1
अगर मैं एंड्रॉइड 5.0.2 सैमसंग डिवाइस पर लीक कैनरी लाइब्रेरी का उपयोग करता हूं तो मेरा ऐप क्रैश हो जाता है। यदि मैं लाइब्रेरी इनिशियलाइज़ेशन को अक्षम करता हूं, तो ऐप ठीक काम करता है।
वैनोमार्ट

15

मुझे इस मुद्दे के बारे में कुछ स्लाइड्स मिलीं।

http://de.slideshare.net/DroidConTLV/android-crash-analysis-and-the-dalvik-garbage-collector-tools-and-tips

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

https://github.com/oba2cat3/GCTest

https://github.com/oba2cat3/logcat2memorygraph

इसके अलावा मुझे इस तरफ टिप्पणी # 3 में एक संकेत मिला: https://code.google.com/p/android/issues/detail?id=53418#c3


7

हमने समस्या को हल करके रोक दिया FinalizerWatchdogDaemon

public static void fix() {
    try {
        Class clazz = Class.forName("java.lang.Daemons$FinalizerWatchdogDaemon");

        Method method = clazz.getSuperclass().getDeclaredMethod("stop");
        method.setAccessible(true);

        Field field = clazz.getDeclaredField("INSTANCE");
        field.setAccessible(true);

        method.invoke(field.get(null));

    }
    catch (Throwable e) {
        e.printStackTrace();
    }
}

आप एप्लिकेशन के जीवनचक्र में विधि को कॉल कर सकते हैं, जैसे attachBaseContext()। उसी कारण से, आप समस्या को ठीक करने के लिए फ़ोन के निर्माण को भी विशिष्ट कर सकते हैं, यह आपके ऊपर है।


हमारे लिए काम नहीं करता है, मैं समझ नहीं पा रहा हूँ क्यों। कोड अपवाद के बिना पूरा होता है, लेकिन हम अभी भी क्रैशलाइटिक्स रिपोर्ट और Google Play कंसोल में उन मुद्दों को प्राप्त करते हैं।
एंटोन ब्रूसोव

5

प्रसारण 10 सेकंड के बाद टाइमआउट प्राप्त करता है। संभवतः आपका प्रसारण प्रसारण रिसीवर से एक एसिंक्रोनस कॉल (गलत) कर रहा है और 4.3 वास्तव में इसका पता लगाता है।


3
यह पता लगाने के लिए बेकार लगता है और आपको इसके बारे में पर्याप्त नहीं बताता है। हमें बताएं कि कौन सा प्रसारण अच्छा होगा।
आरोन टी हैरिस

क्षमा करें यदि मैं गलत हूं, लेकिन मुझे नहीं लगता कि प्रसारण रिसीवर टाइमआउट इस विशेष दुर्घटना का कारण बनता है। यह 10 के दशक की सीमा से बचने के लिए अच्छा अभ्यास है, लेकिन यह आवश्यक से अलग मुद्दा है।
पार्करफैथ

मेरे पास मस्तिष्क पर सिर्फ 10 सेकंड हैं। अगर यह दुर्घटना का कारण बन रहा था, तो डेवलपर .android.com/training/articles/perf-anr.html IDK।
danny117 21

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

मैं यहां डिवाइस को बैश करने के लिए नहीं हूं, यह कहता है कि यह शर्तों के खिलाफ होगा।
danny117

5

इस समस्या को हल करने के लिए दीदी का एक प्रभावी उपाय है, क्योंकि यह बग बहुत ही सामान्य है और इसका कारण खोजना मुश्किल है, यह एक सिस्टम समस्या की तरह दिखता है, हम इसे सीधे अनदेखा क्यों नहीं कर सकते हैं बेशक हम इसे अनदेखा कर सकते हैं, यहाँ नमूना कोड है:

final Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler = 
        Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        if (t.getName().equals("FinalizerWatchdogDaemon") && e instanceof TimeoutException) {
        } else {
            defaultUncaughtExceptionHandler.uncaughtException(t, e);
        }
    }
});

एक विशेष डिफ़ॉल्ट अनकैप्ड अपवाद हैंडलर को सेट करके, एप्लिकेशन उन तरीकों के तरीके को बदल सकता है, जो उन थ्रेड्स के लिए संभाले जाते हैं, जो पहले से ही सिस्टम द्वारा प्रदान किए गए डिफ़ॉल्ट व्यवहार को स्वीकार करेंगे। जब एक TimeoutExceptionथ्रेड नाम के थ्रेड से फेंका जाता है FinalizerWatchdogDaemon, तो यह विशेष हैंडलर हैंडलर श्रृंखला को अवरुद्ध करेगा, सिस्टम हैंडलर को नहीं बुलाया जाएगा, इसलिए दुर्घटना से बचा जाएगा।

अभ्यास के माध्यम से, कोई अन्य बुरा प्रभाव नहीं मिला। जीसी सिस्टम अभी भी काम कर रहा है, सीपीयू का उपयोग कम होने के साथ ही समय समाप्त हो जाता है।

अधिक जानकारी के लिए देखें: https://mp.weixin.qq.com/s/uFcFYO2GtWWiblotem2gGg


4

एक बात जो हमेशा के लिए सही है, वह यह है कि इस समय, डिवाइस कुछ मेमोरी के लिए दम घुट रहा होगा (जो आमतौर पर जीसी के लिए सबसे अधिक ट्रिगर होने का कारण है)।

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

  • यह सुनिश्चित करने के लिए कि कोई मेमोरी लीक न हो, और
  • सामान्य रूप से ऐप के मेमोरी फ़ुटप्रिंट को कम करने के लिए।

1
try {
    Class<?> c = Class.forName("java.lang.Daemons");
    Field maxField = c.getDeclaredField("MAX_FINALIZE_NANOS");
    maxField.setAccessible(true);
    maxField.set(null, Long.MAX_VALUE);
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} catch (NoSuchFieldException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
}

स्लीप की अवधि> 100 सेकंड होने की स्थिति में यह समस्या का समाधान नहीं करेगा। इसे MAX_INT पर सेट क्यों नहीं किया गया?
oba

हां, मैं सिर्फ उदाहरण हूं ~
kot32

1
लगातार इनलाइनिंग के कारण यह काम नहीं करना चाहिए। फील्ड वैल्यू बदलने से कॉल करने वालों को इनबिल्ट वैल्यू प्रभावित नहीं होगी।
हक़्ज़्ज़्ज़ब

0

अंतिम रूपांतर बहुत लंबा हो सकता है

मुझे लगता है कि java को GC.SuppressFinalize () और GC.ReRegisterForFinalize () की आवश्यकता हो सकती है ताकि उपयोगकर्ता अंतिम रूप से निर्धारित लंबाई को कम कर सकें।

यदि JVM 'स्रोत कोड उपलब्ध है, तो इन तरीकों को हमारे आप लागू कर सकते हैं, जैसे कि Android ROM निर्माता


0

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

चलो कुछ कर्सर हैं जो अंतिम विधि में कुछ करते हैं (जैसे SqlCipher वाले, बंद करें () जो उस डेटाबेस में लॉक होता है जो वर्तमान में उपयोग में है)

private static class MyCur extends MatrixCursor {


    public MyCur(String[] columnNames) {
        super(columnNames);
    }

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

        try {
            for (int i = 0; i < 1000; i++)
                Thread.sleep(30);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

और हम कुछ लंबे समय तक चलने वाले सामान को खोलते हुए कर्सर करते हैं:

for (int i = 0; i < 7; i++) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                MyCur cur = null;
                try {
                    cur = new MyCur(new String[]{});
                    longRun();
                } finally {
                    cur.close();
                }
            }

            private void longRun() {
                try {
                    for (int i = 0; i < 1000; i++)
                        Thread.sleep(30);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

यह निम्न त्रुटि का कारण बनता है:

FATAL EXCEPTION: FinalizerWatchdogDaemon
                                                                        Process: la.la.land, PID: 29206
                                                                        java.util.concurrent.TimeoutException: MyCur.finalize() timed out after 10 seconds
                                                                            at java.lang.Thread.sleep(Native Method)
                                                                            at java.lang.Thread.sleep(Thread.java:371)
                                                                            at java.lang.Thread.sleep(Thread.java:313)
                                                                            at MyCur.finalize(MessageList.java:1791)
                                                                            at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:222)
                                                                            at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:209)
                                                                            at java.lang.Thread.run(Thread.java:762)

SqlCipher के साथ उत्पादन संस्करण बहुत ही परिचित है:

12-21 15:40:31.668: E/EH(32131): android.content.ContentResolver$CursorWrapperInner.finalize() timed out after 10 seconds
12-21 15:40:31.668: E/EH(32131): java.util.concurrent.TimeoutException: android.content.ContentResolver$CursorWrapperInner.finalize() timed out after 10 seconds
12-21 15:40:31.668: E/EH(32131): 	at java.lang.Object.wait(Native Method)
12-21 15:40:31.668: E/EH(32131): 	at java.lang.Thread.parkFor$(Thread.java:2128)
12-21 15:40:31.668: E/EH(32131): 	at sun.misc.Unsafe.park(Unsafe.java:325)
12-21 15:40:31.668: E/EH(32131): 	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:161)
12-21 15:40:31.668: E/EH(32131): 	at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:840)
12-21 15:40:31.668: E/EH(32131): 	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:873)
12-21 15:40:31.668: E/EH(32131): 	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1197)
12-21 15:40:31.668: E/EH(32131): 	at java.util.concurrent.locks.ReentrantLock$FairSync.lock(ReentrantLock.java:200)
12-21 15:40:31.668: E/EH(32131): 	at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262)
12-21 15:40:31.668: E/EH(32131): 	at net.sqlcipher.database.SQLiteDatabase.lock(SourceFile:518)
12-21 15:40:31.668: E/EH(32131): 	at net.sqlcipher.database.SQLiteProgram.close(SourceFile:294)
12-21 15:40:31.668: E/EH(32131): 	at net.sqlcipher.database.SQLiteQuery.close(SourceFile:136)
12-21 15:40:31.668: E/EH(32131): 	at net.sqlcipher.database.SQLiteCursor.close(SourceFile:510)
12-21 15:40:31.668: E/EH(32131): 	at android.database.CursorWrapper.close(CursorWrapper.java:50)
12-21 15:40:31.668: E/EH(32131): 	at android.database.CursorWrapper.close(CursorWrapper.java:50)
12-21 15:40:31.668: E/EH(32131): 	at android.content.ContentResolver$CursorWrapperInner.close(ContentResolver.java:2746)
12-21 15:40:31.668: E/EH(32131): 	at android.content.ContentResolver$CursorWrapperInner.finalize(ContentResolver.java:2757)
12-21 15:40:31.668: E/EH(32131): 	at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:222)
12-21 15:40:31.668: E/EH(32131): 	at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:209)
12-21 15:40:31.668: E/EH(32131): 	at java.lang.Thread.run(Thread.java:762)

फिर से शुरू करें: बंद कर्सर ASAP। कम से कम सैमसंग एस 8 पर एंड्रॉइड 7 के साथ जहां समस्या देखी गई है।


0

उन कक्षाओं के लिए जो आप बनाते हैं (यानी Android का हिस्सा नहीं हैं) दुर्घटना से पूरी तरह से बचने के लिए संभव है।

किसी भी वर्ग जो लागू करता है finalize()उसके पास दुर्घटना की कुछ अपरिहार्य संभावना है जैसा कि @ोबा द्वारा समझाया गया है। इसलिए सफाई का प्रदर्शन करने के लिए फाइनल का उपयोग करने के बजाय, का उपयोग करें PhantomReferenceQueue

एक उदाहरण के लिए रिएक्ट नेटिव में कार्यान्वयन की जाँच करें: https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/jni-DestructorThread.java

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.