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 Siecleanup()
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
unddouble
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)
- z. B.
- 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.