Модель памяти J2ObjC

В этом документе описывается, как управляется память в транслированном коде J2ObjC и как программы ведут себя при доступе к общей памяти.

Управление памятью

Одной из целей J2ObjC является создание переведенного кода, который будет легко интегрироваться в среду подсчета ссылок Objective-C. Это упрощает использование переведенного кода Java из изначально написанного Objective-C, поскольку отсутствует неудобная передача прав собственности на объекты, передаваемые между средами Java и Objective-C.

Поскольку Java использует сборку мусора для управления памятью, код Java не содержит явного управления памятью своих объектов. Поэтому J2ObjC должен соответствующим образом вставлять вызовы подсчета ссылок, чтобы гарантировать освобождение объектов в нужное время. Мы остановились на следующем наборе правил, которые, по нашему мнению, являются одновременно эффективными и практичными:

  • Все объекты будут жить как минимум в течение текущего пула автоматического выпуска.
    • Это общее правило позволяет нам пропустить многие операции сохранения и выпуска, которые в противном случае были бы необходимы.
  • Локальные переменные не сохраняются.
    • Нет вызовов подсчета ссылок при чтении или записи локальных переменных.
  • Поля сохраняются.
    • Присвоение поля вызывает сохранение нового значения и автоматическое освобождение старого значения.
  • Новые объекты немедленно автоматически высвобождаются. (если не назначено сразу полю)

Справочные циклы

Ссылочный цикл существует, когда объект ссылается на себя прямо или косвенно через свои поля. Ссылочные циклы можно очистить с помощью сборки мусора Java, но они приведут к утечке памяти в среде подсчета ссылок Objective-C. Не существует автоматического способа предотвращения возникновения эталонных циклов; однако мы предоставляем инструмент Cycle Finder , который автоматизирует обнаружение циклов. Вот несколько распространенных способов исправить эталонный цикл:

  • Добавьте аннотацию @Weak или @WeakOuter , чтобы ослабить одну из ссылок.
  • Добавьте к одному из объектов метод cleanup() , который устанавливает для некоторых полей значение null. Вызовите cleanup() перед удалением объекта.
  • Перепроектируйте код, чтобы вообще избежать создания ссылочного цикла.

Общая память

В многопоточной программе некоторые данные могут совместно использоваться несколькими потоками. Java предоставляет несколько инструментов для обеспечения поточно-безопасного доступа к общим данным. В этом разделе описывается поддержка J2ObjC для доступа к общим данным.

Синхронизировано

J2ObjC сопоставляет ключевое synchronized непосредственно с Objective-C @synchronized .

атомарность

Java гарантирует атомарность для загрузок и сохранений всех типов, кроме long и double . См. JLS-17.7 . За исключением volatile полей (описанных ниже), J2ObjC не предоставляет специальной обработки для обеспечения атомарной загрузки и хранения. Это подразумевает следующее:

  • Поскольку все платформы iOS являются 32- или 64-разрядными, загрузки и сохранения примитивных типов, за исключением long и double , являются атомарными на 32-разрядных устройствах, и все они являются атомарными в 64-разрядных системах.
  • Загрузка и сохранение типов объектов в J2ObjC не являются атомарными.
    • Атомарное обновление счетчика ссылок слишком затратно.
    • Поле объекта можно сделать атомарным, объявив его volatile . (см. ниже)

Неустойчивые поля

Для volatile полей Java обеспечивает как атомарность, так и последовательно согласованный порядок ( JLS-8.3.1.4 ), который можно использовать для синхронизации. J2ObjC предоставляет те же гарантии, что и Java, для всех volatile полей. J2ObjC использует следующие механизмы для volatile полей:

  • Примитивные типы сопоставляются с атомарными типами c11.
    • например. volatile int -> _Atomic(jint)
  • Поля объекта защищены блокировками мьютексов pthread. (невозможно использовать спин-блокировки из-за инверсии приоритета)
    • Взаимное исключение необходимо для предотвращения состояний гонки при подсчете ссылок.
    • Реализация очень похожа на атомарные свойства Objective-C.

Атомные типы

Java предоставляет ряд атомарных типов в пакете java.util.concurrent.atomic . Все они полностью поддерживаются в J2ObjC с помощью пользовательских реализаций.

Заключительные поля

Java гарантирует, что поток видит инициализированные значения для конечных полей объекта, не требуя какой-либо синхронизации при совместном использовании объекта. ( JSL-17.5 ) Однако, поскольку J2ObjC не поддерживает атомарный доступ к энергонезависимым типам объектов (см. выше), не существует безопасного способа совместного использования объекта без синхронизации. Таким образом, на пользователя J2ObjC не накладываются никакие дополнительные ограничения за счет исключения необходимых ограничений памяти для конечных полей.