Model pamięci J2ObjC

Ten dokument zawiera opis zarządzania pamięcią w przetłumaczonym kodzie J2ObjC oraz zachowanie programów podczas uzyskiwania dostępu do pamięci współdzielonej.

Zarządzanie pamięcią

Jednym z celów firmy J2ObjC jest utworzenie przetłumaczonego kodu, który będzie płynnie integrowany ze środowiskiem liczenia plików referencyjnych w Objective-C. Dzięki temu przetłumaczony kod Java jest łatwy do użycia z natywnego języka Objective-C, ponieważ nie trzeba przenosić własności obiektów przekazywanych między środowiskami Java i Objective-C.

Ponieważ Java do zarządzania pamięcią używa funkcji czyszczenia pamięci, kod w niej nie zawiera jawnego zarządzania pamięcią jej obiektów. Dlatego J2ObjC musi odpowiednio wstawiać wywołania zliczania odwołań, aby mieć pewność, że obiekty zostaną przypisane w odpowiednim momencie. Osiągnęliśmy następujące reguły, które naszym zdaniem są zarówno skuteczne, jak i praktyczne:

  • Wszystkie obiekty będą działać co najmniej przez czas trwania bieżącej puli automatycznie zwalnianych.
    • Ta ogólna zasada pozwala nam pominąć wiele blokad i udostępnień, które w innym przypadku byłyby potrzebne.
  • Zmienne lokalne nie są zachowywane.
    • Brak odwołań zliczających wywołania w odczytach lub zapisach zmiennych lokalnych.
  • Pola są zachowywane.
    • Przypisanie wywołań pola zachowuje nową wartość i automatyczne zwolnienie z poprzedniej wartości.
  • Nowe obiekty są natychmiast zwalniane automatycznie. (chyba że dane są natychmiast przypisane do pola)

Cykle referencyjne

Cykl odwołania występuje wtedy, gdy obiekt odnosi się do siebie bezpośrednio lub pośrednio przez swoje pola. Cykle odwołań mogą być czyszczone przez funkcję odśmiecania Javy, ale spowoduje to wyciek pamięci w środowisku zliczania odniesień celu-C. Nie ma sposobu na automatyczne zapobieganie cyklom referencyjnym. Udostępniamy jednak narzędzie Cycle Finder, które automatyzuje wykrywanie cykli. Oto kilka typowych sposobów naprawienia cyklu referencyjnego:

  • Aby osłabić jedno z plików referencyjnych, dodaj adnotację @Weak lub @WeakOuter.
  • Dodaj metodę cleanup() do jednego z obiektów, które ustawiają wartość null niektórych pól. Wywołaj cleanup(), zanim odrzucisz obiekt.
  • Przeprojektować kod tak, aby uniknąć tworzenia cyklu referencyjnego.

Pamięć współdzielona

W programie wielowątkowym niektóre dane mogą być udostępniane w ramach wielu wątków. Java udostępnia kilka narzędzi, które umożliwiają bezpieczny dostęp do udostępnionych danych w wątku. Ta sekcja opisuje, jak J2ObjC obsługuje dostęp do udostępnionych danych.

Synchronizowany

J2ObjC mapuje słowo kluczowe synchronized bezpośrednio na cel typu Objective-C @synchronized.

Atomiczność

Java gwarantuje niepodzielność w przypadku wczytywania i magazynów wszystkich typów z wyjątkiem long i double. Zobacz JLS-17.7. Z wyjątkiem pól volatile (opisanych poniżej) J2ObjC nie zapewnia specjalnego traktowania, aby zapewnić obciążenie atomowe i magazynowanie. Oznacza to, że:

  • Ponieważ wszystkie platformy iOS są 32-bitowe lub 64-bitowe, wczytania i przechowywanie typów podstawowych z wyjątkiem long i double są atomowe na urządzeniach 32-bitowych, a w systemach 64-bitowych są atomowe.
  • Wczytywanie i przechowywanie typów obiektów nie są atomowe w J2ObjC.
    • Atomowe aktualizowanie liczby plików referencyjnych jest zbyt kosztowne.
    • Pole obiektu może stać się atomowe, zadeklarując je volatile. (patrz poniżej)

Pola nietrwałe

W przypadku pól volatile Java zapewnia zarówno nietomiczność, jak i sekwencją spójnego porządku (JLS-8.3.1.4), którego można używać do synchronizacji. J2ObjC zapewnia te same gwarancje co w języku Java we wszystkich polach volatile. J2ObjC używa tych mechanizmów w polach volatile:

  • Typy podstawowe są mapowane na typy atomowe c11.
    • np. volatile int -> _Atomic(jint)
  • Pola obiektów są chronione za pomocą blokad muteksu pThread. (nie można używać blokad obracania z powodu odwrócenia priorytetu)
    • Wzajemne wykluczanie jest konieczne, aby uniknąć sytuacji wyścigowych podczas zliczania plików referencyjnych.
    • Implementacja jest bardzo podobna do właściwości atomowych języka Objective-C.

Typy atomowe

Java udostępnia szereg typów atomowych w pakiecie java.util.concurrent.atomic. Wszystkie te elementy są w pełni obsługiwane w J2ObjC z niestandardowymi implementacjami.

Pola końcowe

Java gwarantuje, że wątek widzi zainicjowane wartości końcowych pól obiektu bez konieczności synchronizacji podczas udostępniania obiektu. (JSL-17.5) Ponieważ jednak J2ObjC nie obsługuje dostępu atomowego do obiektów nieulotnych (patrz wyżej), nie ma bezpiecznego sposobu udostępniania obiektów bez synchronizacji. Dzięki temu nie nakładaj na użytkownika J2ObjC żadnych dodatkowych ograniczeń, pomijając niezbędne granice pamięci dla pól końcowych.