7

Ich verbrachte fast einen ganzen Tag damit, den Grund für ein Speicherleck in Android herauszufinden. Es gibt eine Aktivität, die ich viele Male öffne/schließe (mit einem Timer). Nach einer Weile wurde ich OutOfMemory Fehler bekommen:Sollte GC nicht automatisch in Xamarin.Android ausgeführt werden, bevor nicht genügend Arbeitsspeicher verfügbar ist?

enter image description here

ich die Erinnerung sah jedes Mal die Aktivität geöffnet ständig in Xamarin Profiler hinauf:

enter image description here

stellte ich sicher, es gab keine Immobilien oder Event-Handler, die in dieser Aktivität stecken bleiben könnten. Ich habe sogar jedes Bild, Schaltflächen usw. entfernt, um herauszufinden, was den Speicherverlust verursacht hat. Immer noch das gleiche ...

Dann habe ich GC.Collect() in der OnResume Methode der Haupttätigkeit (die, die die problematische Aktivität öffnet). Jetzt kann ich sehen, wie die Erinnerung auf und ab geht. Sie können das Ergebnis im Screenshot sehen:

enter image description here

Per Xamarin docs:

Der GC wird ausgeführt, wenn der kleine Haufen aus dem Speicher für neue Zuweisungen

ausgeführt wird Aber das passiert nicht wirklich

+3

Relevante Literatur: https://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/#Cross-VM_Object_Collections und http://stackoverflow.com/questions/ 28863058/xamarin-android-finalizer-nicht-immer-aufgerufen-wann-verlassen-die-aktivität-zu-gehen/28868582 # 28868582 – matthewrdev

Antwort

9

Sie möchten vielleicht ein wenig weiter unten in Ihrem Link unter lesen Hilfe für die GC: The GC has an incomplete view of the process and may not run when memory is low because the GC doesn't know that memory is low. und Managed Callable Wrappers do not add additional instance members

Grundsätzlich wäre es BaseActivity erscheinen ist ein Android-Callable Wrapper (ACW) und das Mono GC nicht weiß, wie groß es ist, so dass es nicht zu berufen weiß der Müllsammler. Soweit ich weiß, ist die ACW eine Möglichkeit, Android-Schnittstellen zu implementieren.

Die Lösung ist, wie Sie festgestellt haben, manuell den Garbage Collector aufzurufen, der in den Xamarin-Dokumenten empfohlen wird, wenn ACWs verwendet werden.

http://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/

----

Seit der ursprünglichen Veröffentlichung von dieser Antwort hat die Xamarin docs in ihrer Erklärung für diese Situation verbessert:

Eine Instanz eines Java .Lang.Object-Typ oder abgeleiteter Typ ist mindestens 20 Byte groß. Verwaltete abrufbare Wrapper fügen keine zusätzlichen Instanzen der Instanz hinzu. Wenn Sie also eine Instanz von Android.Graphics.Bitmap haben, die auf einen 10 MB-Speicherblob verweist, weiß Xamarin.Androids GC nicht, dass - der GC eine 20- Byte-Objekt und kann nicht feststellen, dass es mit Android Runtime-allokierte Objekte verknüpft ist, die 10 MB Speicher am Leben erhalten.

Dies zeigt, dass, unabhängig davon, ob Objekte gesetzt oder nicht auf null, sollten Sie noch die Xamarin GC manuell aufrufen, wenn Sie Zuweisen/Freigeben von Callable Wrappers, die möglicherweise eine große Menge verbrauchen Erinnerung.

Unter der Annahme ein Java Object ist 20 Bytes, wenn man 100 Objekte zuweisen und Null, die jeweils 10MB verbrauchen, der Xamarin GC glaubt, dass 4000 Bytes des Speichers verwendet werden. In Wirklichkeit wird ~ 1 GB benutzt, und der GC kann oder kann nicht aufgerufen werden.

-3

Durch den Aufruf der Garbage Collection wird nicht sichergestellt, dass die Garbage Collection ausgeführt wird oder dass alle Speicherzuordnungen ausgeführt werden. Oftmals geht es darum, einen Verweis auf ein Objekt zu entfernen. Wenn ein Objekt einen Verweis darauf hat, wird kein Müll gesammelt. Ich musste das auf die harte Tour lernen. Um dieses Problem zu jedem Zeitpunkt zu beheben, können Sie jederzeit ein Objekt aufheben und es bei Bedarf einfach einstellen. Beispiel:

CustomObject cusObj = null; 
if (cusObj == null) 
{ 
    cusObj = new CustomObject(); 
} 

Einfach sicherstellen, dass Sie das Objekt löschen, wird die Referenz entfernt. Aber wie in der Antwort oben erwähnt, können Sie Müll sammeln. Denken Sie daran, dass der GC keinen Müll mit einer Referenz sammelt. Werfen Sie einen Blick auf:

Garbage collection and references C#

+0

Wie Sie in der Frage lesen können, ist es kein Referenzproblem, weil ich dafür gesorgt habe Alles sauber – xleon

+0

Nicht wahr Die größte Ursache für Heap-Speicherfehler sind Verweise auf Objekte, die es dem Garbage Collector nicht erlauben, dort zu arbeiten. – yams

+0

Nulled Ihre Objekte, um die Referenz loszuwerden, wäre das Problem in erster Linie losgeworden. – yams

Verwandte Themen