Arbeitsspeicherverwaltung

Die erste Frage, die die meisten Java-Entwickler haben, ist, wie die Arbeitsspeicherverwaltung von J2ObjC implementiert wird, da Java über eine automatische Speicherbereinigung verfügt und Objective-C dies nicht standardmäßig tut. iOS bietet zwei Methoden zur Speicherverwaltung: Referenzzählung und automatische Referenzzählung (ARC).

J2ObjC generiert unterschiedlichen Speicherverwaltungscode, je nachdem, welche Methode ausgewählt wurde. Übersetzen Sie mit der Option -use-arc, um Code mithilfe von ARC zu generieren. Standardmäßig wird die manuelle Referenzzählung verwendet.

Referenzzählung

Durch die Zählmethode für Referenzen wird die Objektinhaberschaft explizit festgelegt. Eine Methode ist Inhaber eines Objekts, wenn sie es erstellt, bis sie dieses Objekt freigibt. Wenn ein Objekt von einer anderen Methode empfangen wird, behält die empfangende Methode das Objekt bei, wenn es referenziert werden muss, nachdem die Methode zurückgegeben wurde. Wenn eine Methode nicht mehr auf ein Objekt verweisen muss, muss sie freigegeben werden. Wenn die Anzahl der Aufbewahrungen eines Objekts null ist, wird sein Arbeitsspeicher freigegeben und das Objekt ist nicht mehr gültig. Wenn Objekte freigegeben werden, wird ihre Methode "Dealloc()" aufgerufen, um die Inhaberschaft ihrer Instanzvariablen freizugeben.

Ein Problem bei dieser Technik besteht darin, die Inhaberschaft eines Objekts zu übertragen. Beispielsweise kann eine Factory-Methode aufgerufen werden, um ein Objekt zu erstellen. Wenn die Factory-Methode das Objekt vor der Rückgabe freigibt (da sie nicht mehr Inhaber des Objekts sein möchte), wird dieses Objekt freigegeben, bevor es von der aufrufenden Methode beibehalten werden kann.

Zum Übertragen der Inhaberschaft eines Objekts sendet eine Methode eine Autorelease-Nachricht anstelle einer Release-Nachricht, wodurch die Release-Nachricht aufgeschoben wird. Dadurch kann die Factory-Methode ein Objekt erstellen, das zurückgegeben werden kann, und seine Inhaberschaft abgeben, ohne das Objekt zu entwerten. In regelmäßigen Intervallen (z. B. nach jeder Iteration einer Ereignisschleife in einer iOS-App) wird der automatische Release-Pool „drained“. Das bedeutet, dass alle Objekte in diesem Pool die verzögerten Release-Nachrichten gesendet werden. Alle Objekte, deren Anzahl auf null sinkt, werden wie gewohnt freigegeben.

Da die Last der Speicherverwaltung auf den Entwickler liegt, können bei der Referenzzählmethode Speicherlecks auftreten. Apple empfiehlt jedoch einige Best Practices, um dieses Problem zu minimieren, das von J2ObjC implementiert wird.

Es gibt auch Laufzeit- und Toolunterstützung, um Speicherlecks zu erkennen. Die Objective-C-Laufzeit meldet alle erkannten Schwachstellen, wenn eine Anwendung beendet wird. Dies ist einer der Gründe, warum J2ObjC JUnit-Tests in ausführbare Binärdateien übersetzt. Xcode verwendet Clang und dieser Compiler bietet eine hervorragende statische Analyse für Speicherprobleme, die Xcode mit dem Befehl "Analyze" zur Verfügung stellt.

Automatische Referenzzählung (ARC)

ARC ist die von Apple empfohlene Methode zur Speicherverwaltung. Die Zuständigkeit für die Referenzzählung wird dem Compiler übertragen, der während der Kompilierung die entsprechenden Methoden zur Aufbewahrung, Veröffentlichung und zum automatischen Veröffentlichung hinzufügt. ARC unterstützt schwache Referenzen für Geräte mit iOS 5 und höher.

Wir empfehlen, für übersetzten Code ARC zu verwenden. Transpilierter Objective-C-Code entspricht dem von Hand geschriebenen Objective-C-Code. Die Verwendung von ARC könnte Entwicklern helfen, häufige speicherbezogene Fehler wie eine übermäßige Freigabe oder Unterreferenz zu vermeiden. Dadurch wird die Speicherverwaltung einfacher und weniger fehleranfällig.

Beachten Sie, dass ARC standardmäßig nicht besonders sicher ist. Insbesondere tritt ein Speicherleck auf, wenn Ausnahmen ausgelöst werden. Da Ausnahmen in Java häufiger vorkommen und in der Regel wiederherstellbar sind, kann dies problematisch sein. Wenn Sie beim Kompilieren mit Arc -fobjc-arc-exceptions verwenden, können Schwachstellen mit akzeptablen Leistungskosten behoben werden.

Neue Projekte empfehlen außerdem, ARC für handgeschriebenen Objective-C-Code zu verwenden und nur dann auf die manuelle Referenzzählung zurückzugreifen, wenn Profildaten ein echtes Leistungsproblem aufweisen. Sowohl ARC- als auch Nicht-ARC-Code können problemlos kompiliert und mit derselben Anwendung verknüpft werden.

Schwache Referenzen

Felder können mit com.google.devtools.j2objc.Weak annotiert werden. Damit generiert der Transpiler Felder, die der schwachen Referenzsemantik von Objective-C entsprechen. Bei der Referenzzählung bedeutet dies, dass das Feld bei der Initialisierung nicht beibehalten und automatisch freigegeben wird, wenn die enthaltende Instanz freigegeben wird. Bei ARC werden schwache Felder mit der Annotation __unsafe_unretained gekennzeichnet und die zugehörigen Attribute als schwach deklariert.

In einigen Fällen befindet sich eine innere Klasseninstanz in einem Referenzzyklus mit ihrer äußeren Instanz. Hier wird die Annotation com.google.devtools.j2objc.WeakOuter verwendet, um die innere Klasse zu kennzeichnen, sodass der Verweis auf die äußere Klasse wie oben beschrieben behandelt wird. Andere Felder in der inneren Klasse sind von dieser Annotation nicht betroffen.

J2ObjC unterstützt auch die Klasse WeakReference, sodass Java-Code, der sie verwendet, in der Übersetzung genauso funktioniert. Beachten Sie, dass WeakReference in der JVM grundsätzlich nicht deterministisch ist. Anwendungen, die Speicherlecks vermeiden und gleichzeitig die Vorhersehbarkeit gewährleisten möchten, sollten stattdessen @Weak und @WeakOuter bevorzugen.

Tools zur Arbeitsspeicherverwaltung