J2ObjC-Speichermodell

In diesem Dokument wird beschrieben, wie der Arbeitsspeicher mit übersetztem J2ObjC-Code verwaltet wird und wie sich Programme beim Zugriff auf den freigegebenen Speicher verhalten.

Arbeitsspeicherverwaltung

Eines der Ziele von J2ObjC ist die Erstellung von übersetztem Code, der sich nahtlos in die Referenzzählungsumgebung von Objective-C einbinden lässt. Dadurch ist übersetzter Java-Code aus nativ geschriebenem Objective-C einfach zu verwenden, da keine umständliche Übertragung der Eigentümerschaft für Objekte zwischen Java- und Objective-C-Umgebungen erfolgt.

Da Java zur Speicherverwaltung die automatische Speicherbereinigung verwendet, enthält der Java-Code keine explizite Speicherverwaltung seiner Objekte. J2ObjC muss daher Referenzzählungsaufrufe entsprechend einfügen, um sicherzustellen, dass Objekte zur richtigen Zeit freigegeben werden. Wir haben die folgenden Regeln festgelegt, die sich sowohl als leistungsfähig als auch praktisch erwiesen haben:

  • Alle Objekte sind mindestens für die Dauer des aktuellen Pools für automatische Veröffentlichung verfügbar.
    • Durch diese allgemeine Regel können wir viele Aufbewahrungen und Releases überspringen, die sonst notwendig wären.
  • Lokale Variablen werden nicht beibehalten.
    • Keine Referenz, die Aufrufe bei Lese- oder Schreibvorgängen lokaler Variablen zählt.
  • Felder bleiben erhalten.
    • Bei der Zuweisung eines Feldaufrufs wird der neue Wert beibehalten und der alte Wert automatisch freigegeben.
  • Neue Objekte werden sofort automatisch freigegeben. (sofern nicht sofort einem Feld zugewiesen)

Referenzzyklen

Ein Referenzzyklus besteht, wenn ein Objekt entweder direkt oder indirekt über seine Felder auf sich selbst verweist. Referenzzyklen können durch die automatische Speicherbereinigung von Java bereinigt werden, verursachen jedoch in der Referenzzählumgebung von Objective-C Speicherlecks. Es gibt keine automatisierte Methode, das Auftreten von Referenzzyklen zu verhindern. Wir stellen jedoch ein Tool zur Zyklussuche zur Verfügung, das die Erkennung von Zyklen automatisiert. Hier sind einige gängige Möglichkeiten zur Behebung eines Referenzzyklus:

  • Mit einer @Weak- oder @WeakOuter-Annotation können Sie eine der Referenzen schwächen.
  • Fügen Sie einem der Objekte eine cleanup()-Methode hinzu, durch die einige Felder auf null gesetzt werden. Rufen Sie cleanup() auf, bevor Sie das Objekt verwerfen.
  • Gestalten Sie den Code neu, damit Sie überhaupt keinen Referenzzyklus erstellen müssen.

Gemeinsamer Speicher

In einem Multi-Threaded-Programm können einige Daten von mehreren Threads geteilt werden. Java bietet mehrere Tools, die Thread-sicheren Zugriff auf freigegebene Daten ermöglichen. In diesem Abschnitt wird die J2ObjC-Unterstützung für den Zugriff auf freigegebene Daten beschrieben.

Synchronisiert

J2ObjC ordnet das Schlüsselwort synchronized direkt Objective-C @synchronized zu.

Atomarität

Java garantiert die Atomarität für Ladevorgänge und Speicher aller Typen außer long und double. Siehe JLS-17.7. Mit Ausnahme der unten beschriebenen volatile-Felder bietet J2ObjC keine besondere Behandlung, um atomare Ladevorgänge und Speicher sicherzustellen. Dies impliziert Folgendes:

  • Da alle iOS-Plattformen 32- oder 64-Bit haben, sind Ladevorgänge und Speicher von primitiven Typen mit Ausnahme von long und double auf 32-Bit-Geräten atomar und alle sind auf 64-Bit-Systemen atomar.
  • Lade- und Speichervorgänge von Objekttypen sind in J2ObjC nicht atomar.
    • Die atomare Aktualisierung von Referenzzahlen ist zu kostspielig.
    • Ein Objektfeld kann durch die Deklaration volatile atomar werden. (siehe unten)

Flüchtige Felder

Für volatile-Felder bietet Java sowohl eine Atomarität als auch eine sequentielle konsistente Reihenfolge (JLS-8.3.1.4), die für die Synchronisierung verwendet werden kann. J2ObjC bietet für alle volatile-Felder dieselben Garantien wie Java. J2ObjC verwendet für volatile-Felder die folgenden Mechanismen:

  • Einfache Typen werden atomaren c11-Typen zugeordnet.
    • z. B. volatile int -> _Atomic(jint)
  • Objektfelder sind durch pthread-Mutex-Sperren geschützt. (Sie können aufgrund der Prioritätsumkehrung keine Spinlocks verwenden.)
    • Ein gegenseitiger Ausschluss ist erforderlich, um Race-Bedingungen mit der Referenzzählung zu verhindern.
    • Die Implementierung ist den atomaren Objective-C-Eigenschaften sehr ähnlich.

Atomtypen

Java bietet eine Reihe von atomaren Typen im Paket java.util.concurrent.atomic. Diese werden alle in J2ObjC vollständig mit benutzerdefinierten Implementierungen unterstützt.

Endgültige Felder

Java garantiert, dass ein Thread initialisierte Werte für die endgültigen Felder eines Objekts erkennt, ohne dass eine Synchronisierung erforderlich ist, wenn das Objekt freigegeben wird. (JSL-17.5) Da J2ObjC den atomaren Zugriff auf nichtflüchtige Objekttypen jedoch nicht unterstützt (siehe oben), gibt es keine sichere Möglichkeit, ein Objekt ohne Synchronisierung freizugeben. Daher werden für den J2ObjC-Nutzer keine zusätzlichen Einschränkungen durch Weglassen der erforderlichen Speicherzäune für endgültige Felder festgelegt.