Vorgehensweise: java.util.concurrent.TimeoutException: android.os.BinderProxy.finalize () ist nach 10 Sekunden abgelaufen?

166

Wir sehen eine Reihe von TimeoutExceptionsin GcWatcher.finalize, BinderProxy.finalizeund PlainSocketImpl.finalize. 90 +% davon passieren auf Android 4.3. Wir erhalten Berichte darüber von Crittercism von Benutzern vor Ort.

Geben Sie hier die Bildbeschreibung ein

Der Fehler ist eine Variation von: " 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)

Bisher hatten wir kein Glück, das Problem im Haus zu reproduzieren oder herauszufinden, was es verursacht haben könnte.

Irgendwelche Ideen, was das verursachen kann? Irgendeine Idee, wie man dies debuggt und herausfindet, welcher Teil der App dies verursacht? Alles, was Licht in das Problem bringt, hilft.

Weitere Stacktraces:

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
emmby
quelle
2
Egal , fand es bugzilla.mozilla.org/show_bug.cgi?id=864102 Ich kann auch bestätigen, dass es unsere Apps betrifft, es riecht nach einem Problem mit Google Play Services
eveliotc
Die Codezeile, in der der Fehler ausgelöst wird, wurde in Version 4.3_r1 eingeführt, die am 5. Juni 2013 veröffentlicht wurde. Möglicherweise tritt das Problem seitdem auf.
Edubriguenti
Android Version 4.2.2 hat ebenfalls damit begonnen, diese Ausnahme auszulösen. Vielleicht handelt es sich also um ein Google Play-Update, das die Quelle ist.
JWqvist
@EvelioTarazona Ich habe es in einer App, die keine Spieldienste verwendet
Ligi
@ligi ist es der gleiche Stack-Trace für dich?
Eveliotc

Antworten:

220

Vollständige Offenlegung - Ich bin der Autor des zuvor erwähnten Vortrags in TLV DroidCon.

Ich hatte die Gelegenheit, dieses Problem in vielen Android-Anwendungen zu untersuchen und mit anderen Entwicklern zu diskutieren, die darauf gestoßen sind - und wir kamen alle zum gleichen Punkt: Dieses Problem kann nicht vermieden, sondern nur minimiert werden.

Ich habe mir die Standardimplementierung des Android Garbage Collector-Codes genauer angesehen, um besser zu verstehen, warum diese Ausnahme ausgelöst wird und welche möglichen Ursachen dies haben könnte. Ich habe sogar eine mögliche Ursache beim Experimentieren gefunden.

Die Wurzel des Problems liegt an dem Punkt, an dem ein Gerät für eine Weile in den Ruhezustand wechselt. Dies bedeutet, dass das Betriebssystem beschlossen hat, den Batterieverbrauch zu senken, indem die meisten User Land-Prozesse für eine Weile gestoppt und der Bildschirm ausgeschaltet werden, wodurch die CPU-Zyklen verkürzt werden usw. Die Vorgehensweise erfolgt auf Linux-Systemebene, auf der die Prozesse während der Ausführung angehalten werden. Dies kann jederzeit während der normalen Ausführung der Anwendung geschehen, wird jedoch bei einem systemeigenen Systemaufruf beendet, da die Kontextumschaltung auf Kernelebene erfolgt. Also - hier schließt sich der Dalvik GC der Geschichte an.

Der Dalvik GC-Code (wie im Dalvik-Projekt auf der AOSP-Site implementiert) ist kein komplizierter Code. Die grundlegende Funktionsweise wird in meinen DroidCon-Folien behandelt. Was ich nicht behandelt habe, ist die grundlegende GC-Schleife - an dem Punkt, an dem der Sammler eine Liste von Objekten hat, die finalisiert (und zerstört) werden müssen. Die Schleifenlogik an der Basis kann folgendermaßen vereinfacht werden:

  1. nehmen starting_timestamp,
  2. Objekt entfernen für Liste der freizugebenden Objekte,
  3. Objekt freigeben - finalize()und destroy()bei Bedarf native aufrufen ,
  4. nehmen end_timestamp,
  5. berechne ( end_timestamp - starting_timestamp) und vergleiche mit einem fest codierten Timeout-Wert von 10 Sekunden,
  6. Wenn das Timeout erreicht ist, werfen Sie das java.util.concurrent.TimeoutExceptionund beenden Sie den Vorgang.

Stellen Sie sich nun das folgende Szenario vor:

Die Anwendung läuft mit.

Dies ist keine Anwendung für Benutzer, sondern wird im Hintergrund ausgeführt.

Während dieser Hintergrundoperation werden Objekte erstellt, verwendet und müssen gesammelt werden, um Speicher freizugeben.

Die Anwendung stört sich nicht an einem WakeLock, da dies den Akku nachteilig beeinflusst und unnötig erscheint.

Dies bedeutet, dass die Anwendung von Zeit zu Zeit den GC aufruft.

Normalerweise wird der GC-Lauf ohne Probleme abgeschlossen.

Manchmal (sehr selten) entscheidet sich das System, mitten im GC-Lauf zu schlafen.

Dies geschieht, wenn Sie Ihre Anwendung lange genug ausführen und die Dalvik-Speicherprotokolle genau überwachen.

Wenn Sie nun die Zeitstempellogik der grundlegenden GC-Schleife berücksichtigen, kann das Gerät start_stampbeim destroy()nativen Aufruf eines Systemobjekts den Lauf starten, einen nehmen und in den Ruhezustand wechseln.

Wenn es aufwacht und den Lauf fortsetzt, destroy()wird das beendet und das nächste end_stampist die Zeit, die der destroy()Anruf entgegengenommen wurde + die Schlafzeit.

Wenn die Schlafzeit lang war (mehr als 10 Sekunden), java.util.concurrent.TimeoutExceptionwird die geworfen.

Ich habe dies in den Diagrammen gesehen, die mit dem Analyse-Python-Skript erstellt wurden - für Android-Systemanwendungen, nicht nur für meine eigenen überwachten Apps.

Sammeln Sie genügend Protokolle und Sie werden es schließlich sehen.

Endeffekt:

Das Problem kann nicht vermieden werden - Sie werden darauf stoßen, wenn Ihre App im Hintergrund ausgeführt wird.

Sie können Abhilfe schaffen, indem Sie ein WakeLock nehmen und verhindern, dass das Gerät in den Ruhezustand wechselt. Dies ist jedoch eine ganz andere Geschichte, neue Kopfschmerzen und möglicherweise ein weiteres Gespräch in einem anderen Umfeld.

Sie können das Problem minimieren, indem Sie GC-Anrufe reduzieren - wodurch das Szenario weniger wahrscheinlich wird (Tipps finden Sie auf den Folien).

Ich hatte noch keine Gelegenheit, den Dalvik 2 (auch bekannt als ART) GC-Code zu lesen, der über eine neue Generational Compacting-Funktion verfügt, oder Experimente mit einem Android Lollipop durchzuführen.

Hinzugefügt am 05.07.2015:

Nach Überprüfung der Aggregation von Absturzberichten für diesen Absturztyp scheinen diese Abstürze ab Version 5.0 des Android-Betriebssystems (Lollipop mit ART) nur 0,5% dieses Absturztyps zu verursachen. Dies bedeutet, dass die ART GC-Änderungen die Häufigkeit dieser Abstürze verringert haben.

Hinzugefügt am 01.06.2016:

Es sieht so aus, als hätte das Android-Projekt viele Informationen darüber hinzugefügt, wie der GC in Dalvik 2.0 (auch bekannt als ART) funktioniert.

Sie können hier darüber lesen - Debuggen der ART Garbage Collection .

Außerdem werden einige Tools erläutert, mit denen Sie Informationen zum GC-Verhalten Ihrer App abrufen können.

Das Senden eines SIGQUIT an Ihren App-Prozess führt im Wesentlichen zu einer ANR und speichert den Anwendungsstatus zur Analyse in einer Protokolldatei.

oba
quelle
In meinem Fall habe ich auch vor, dies zu mildern, indem ich Wege finde, um die Menge an Code / Zeit, die ich im Hintergrund ausführe, zu reduzieren. Vielen Dank für Ihre Recherche zu diesem Thema.
Parkerfath
Das Entfernen von Hintergrundverarbeitungen in Ihrer App trägt erheblich zur Reduzierung des Problems bei.
Oba
Für das, was es wert ist, geschieht dies immer noch in Marshmallow (6.0.1). Trotzdem habe ich diesen Fehler nur einmal erhalten. Es scheint also kein gigantisches Problem zu sein. Vielen Dank für Ihre gründliche Erklärung.
Knossos
Nach einiger Zeit hatte ich den deutlichen Eindruck, dass die Behebung dieses Problems im Betriebssystem sehr problematisch ist und eine Zusammenarbeit zwischen Google und den OEMs erfordert. Ich erwarte nicht, dass dies bald behoben wird.
Oba
Ich verwende Wakelock, bin aber auf Android 4.4.2 immer noch auf dieses Problem gestoßen. Meine App verfügt über einige Hintergrundfunktionen, ist jedoch hauptsächlich dafür ausgelegt, den ganzen Tag zu arbeiten, während das Ladekabel montiert ist. Gibt es eine andere Möglichkeit, dieses Problem zu beheben?
Orcun Sevsay
74

Wir sehen dies ständig in unserer App mithilfe von Crashlytics. Der Absturz ereignet sich normalerweise weit unten im Plattformcode. Eine kleine Auswahl:

Das Zeitlimit für android.database.CursorWindow.finalize () ist nach 10 Sekunden abgelaufen

java.util.regex.Matcher.finalize () ist nach 10 Sekunden abgelaufen

android.graphics.Bitmap $ BitmapFinalizer.finalize () ist nach 10 Sekunden abgelaufen

Das Zeitlimit für org.apache.http.impl.conn.SingleClientConnManager.finalize () ist nach 10 Sekunden abgelaufen

java.util.concurrent.ThreadPoolExecutor.finalize () ist nach 10 Sekunden abgelaufen

android.os.BinderProxy.finalize () ist nach 10 Sekunden abgelaufen

android.graphics.Path.finalize () ist nach 10 Sekunden abgelaufen

Die Geräte, auf denen dies geschieht, sind überwiegend (aber nicht ausschließlich) Geräte von Samsung. Das könnte nur bedeuten, dass die meisten unserer Benutzer Samsung-Geräte verwenden. Alternativ könnte dies auf ein Problem mit Samsung-Geräten hinweisen. Ich bin mir nicht wirklich sicher.

Ich nehme an, dies beantwortet Ihre Fragen nicht wirklich, aber ich wollte nur bekräftigen, dass dies ziemlich häufig erscheint und nicht spezifisch für Ihre Anwendung ist.

Kevin Coppock
quelle
16
Dies geschieht auch für die Android 5.0.1-Version und scheint nicht auf Samsung-Geräte beschränkt zu sein. Es geschah auf Nexus 6.
Shobhit Puri
4
Ich habe dieses Problem auf Android 4.4.4 mit Gerät von XIAOMI
Paresh Dudhat
Ich wollte nur darauf hinweisen, dass wir die meisten dieser Abstürze auf Samsung-Tablets sehen. Ich bin mir nicht sicher, was Samsung anders gemacht hat, wie Tablets mit Apps im Hintergrund umgehen.
FriendlyMikhail
1
Ich habe dieses Problem auf Android 4.4.4. Gerät von HUAWEI hergestellt.
Rameshbabu
1
Meine App stürzt danach ab, wenn ich eine Leck-Kanarienbibliothek auf einem Android 5.0.2 Samsung-Gerät verwende. Wenn ich die Bibliotheksinitialisierung deaktiviere, funktioniert die App einwandfrei.
Vanomart
15

Ich habe einige Folien zu diesem Thema gefunden.

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

In diesen Folien erklärt der Autor, dass es ein Problem mit GC zu sein scheint, wenn sich viele Objekte oder große Objekte auf dem Haufen befinden. Die Folie enthält auch einen Verweis auf eine Beispiel-App und ein Python-Skript, um dieses Problem zu analysieren.

https://github.com/oba2cat3/GCTest

https://github.com/oba2cat3/logcat2memorygraph

Außerdem habe ich in Kommentar 3 auf dieser Seite einen Hinweis gefunden: https://code.google.com/p/android/issues/detail?id=53418#c3

Christopher
quelle
7

Wir haben das Problem gelöst, indem wir das gestoppt haben 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();
    }
}

Sie können die Methode im Lebenszyklus der Anwendung aufrufen, z attachBaseContext(). Aus dem gleichen Grund können Sie auch die Herstellung des Telefons angeben, um das Problem zu beheben. Es liegt an Ihnen.

Enaoi
quelle
Funktioniert bei uns nicht, ich kann nicht verstehen warum. Der Code wird ausnahmslos vervollständigt, aber wir erhalten diese Probleme weiterhin in Crashlytics-Berichten und in der Google Play Console.
Anton Breusov
5

Zeitüberschreitung für Broadcast-Empfänger nach 10 Sekunden. Möglicherweise führen Sie einen asynchronen Anruf (falsch) von einem Rundfunkempfänger aus und 4.3 erkennt ihn tatsächlich.

danny117
quelle
3
Scheint nutzlos, es zu erkennen und Ihnen nicht genug darüber zu erzählen. Lassen Sie uns wissen, welche Sendung schön wäre.
Aaron T Harris
Entschuldigen Sie, wenn ich falsch liege, aber ich glaube nicht, dass das Zeitlimit für den Rundfunkempfänger diesen bestimmten Absturz verursacht. Es ist eine gute Praxis, das 10s-Limit zu vermeiden, aber das ist ein anderes Problem als das des Antragstellers.
Parkerfath
Ich habe nur 10 Sekunden im Gehirn. developer.android.com/training/articles/perf-anr.html IDK, wenn es den Absturz verursacht hat.
danny117
Ihr Punkt ist solide und eine gute Praxis. Das Originalplakat enthält jedoch eine bestimmte Frage zu einem bestimmten Gerätesatz. Ich würde anderen Zuschauern dieses Beitrags raten, die Antwort von Christopher und oba zu überprüfen, wenn sie dieselben Symptome sehen (Samsung-Geräte (insbesondere Galaxy S 4) usw.)
Parkerfath
Ich bin nicht hier, um Gerätehersteller zu verprügeln, es wäre gegen die Bedingungen.
danny117
5

Hier ist eine effektive Lösung von didi, um dieses Problem zu lösen. Da dieser Fehler sehr häufig und schwer zu finden ist, sieht es eher nach einem Systemproblem aus. Warum können wir ihn nicht direkt ignorieren? Natürlich können wir ihn hier ignorieren ist der Beispielcode:

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);
        }
    }
});

Durch Festlegen eines speziellen Standard-Handlers für nicht erfasste Ausnahmen kann die Anwendung die Art und Weise ändern, in der nicht erfasste Ausnahmen für Threads behandelt werden, die bereits das vom System bereitgestellte Standardverhalten akzeptieren. Wenn ein Ungefangener TimeoutExceptionaus einem Thread mit dem Namen geworfen FinalizerWatchdogDaemonwird, blockiert dieser spezielle Handler die Handlerkette, der Systemhandler wird nicht aufgerufen, sodass ein Absturz vermieden wird.

Durch Übung wurden keine anderen schlechten Effekte gefunden. Das GC-System funktioniert noch, Zeitüberschreitungen werden verringert, wenn die CPU-Auslastung abnimmt.

Weitere Informationen finden Sie unter: https://mp.weixin.qq.com/s/uFcFYO2GtWWiblotem2bGg

Kiwi
quelle
4

Eine Sache, die ausnahmslos zutrifft, ist, dass das Gerät zu diesem Zeitpunkt für einen gewissen Speicher erstickt (was normalerweise der Grund dafür ist, dass GC höchstwahrscheinlich ausgelöst wird).

Wie bereits von fast allen Autoren erwähnt, tritt dieses Problem auf, wenn Android versucht, GC auszuführen, während sich die App im Hintergrund befindet. In den meisten Fällen, in denen wir dies beobachtet haben, hat der Benutzer die App angehalten, indem er den Bildschirm gesperrt hat. Dies kann auch auf einen Speicherverlust irgendwo in der Anwendung hinweisen oder darauf, dass das Gerät bereits zu stark ausgelastet ist. Der einzig legitime Weg, dies zu minimieren, ist:

  • um sicherzustellen, dass keine Speicherlecks auftreten, und
  • um den Speicherbedarf der App im Allgemeinen zu reduzieren.
Sankalp Sharma
quelle
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();
}
kot32
quelle
Dies löst das Problem nicht, wenn die Schlafdauer> 100 Sekunden ist. Warum nicht auf MAX_INT setzen?
Oba
Ja, ich mache nur Beispiel ~
kot32
1
Dies sollte wegen ständigem Inlining nicht funktionieren. Das Ändern des Feldwerts wirkt sich nicht auf den Wert aus, der Anrufern angezeigt wird.
Hqzxzwb
0

Die finalizeQueue ist möglicherweise zu lang

Ich denke, dass Java möglicherweise GC.SuppressFinalize () & GC.ReRegisterForFinalize () erfordert , damit der Benutzer die finalizedQueue- Länge explizit reduzieren kann

Wenn der Quellcode der JVM verfügbar ist, können Sie diese Methode selbst implementieren, z. B. Android ROM Maker

Ja, ja
quelle
0

Es scheint wie ein Android Runtime-Fehler. Es scheint einen Finalizer zu geben, der in einem separaten Thread ausgeführt wird und die Methode finalize () für Objekte aufruft, wenn sie sich nicht im aktuellen Frame des Stacktraces befinden. Der folgende Code (der zur Überprüfung dieses Problems erstellt wurde) endete beispielsweise mit dem Absturz.

Lassen Sie uns einen Cursor haben, der etwas in der Finalize-Methode tut (z. B. SqlCipher-Cursor, do close (), der die derzeit verwendete Datenbank sperrt).

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();
        }
    }
}

Und wir machen einige lang laufende Sachen, nachdem wir den Cursor geöffnet haben:

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();
    }

Dies verursacht folgenden Fehler:

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)

Die Produktionsvariante mit SqlCipher ist sehr ähnlich:

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)

Fortsetzen: Schließen Sie die Cursor so schnell wie möglich. Zumindest auf Samsung S8 mit Android 7, wo das Problem gesehen wurde.

vbevans94
quelle
0

Für Klassen, die Sie erstellen (dh die nicht Teil von Android sind), ist es möglich, den Absturz vollständig zu vermeiden.

Jede Klasse, die implementiert, finalize()hat eine unvermeidbare Wahrscheinlichkeit eines Absturzes, wie von @oba erklärt. Verwenden Sie also a, anstatt Finalizer für die Bereinigung zu verwendenPhantomReferenceQueue .

Ein Beispiel finden Sie in der Implementierung in React Native: https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/jni/DestructorThread.java

Ben
quelle