Языковые привязки с использованием несжатой памяти для языков без гарантированных деструкторов?

Когда кто-то делает привязки из библиотеки C к Java (или любому другому языку с мусором без деструкторов, которые гарантированно работают), как они справляются с правильным освобождением памяти без мусора?

РЕДАКТИРОВАТЬ: То, о чем я думаю (я знаю, что это не указано явно в моем первоначальном вопросе), это когда часть памяти не-gc содержит ссылки на другие ресурсы не-gc, которые должны быть освобождены, когда это объект освобожден. Например, если у вас есть узел связанного списка, не относящийся к gc, который является главой длинного списка таких узлов, и вы хотите, чтобы система gc в конце концов автоматически его очистила, как вы это настроите?

3 ответа

Решение

В Java у вас есть концепция finalize(). Вы можете освободить C-память там.

Однако, вероятно, лучший способ - использовать PhantomReferences вместе с ReferenceQueue. Вы можете расширить класс PhantomReference, чтобы он содержал некоторый идентификатор или указатель или что-либо еще в памяти C-стороны, которую нужно освободить. Когда он ставится в очередь в ReferenceQueue, вы можете освободить память на стороне C, на которую указывает этот идентификатор - объект Java гарантированно больше не существует "в Java".

Обычно они предоставляют API для создания и выпуска ссылки.

Например, собственный интерфейс Java предоставляет глобальные ссылки, которые позволяют закреплять объект Java в памяти до тех пор, пока программа C не завершит его с помощью NewGlobalRef а также DeleteGlobalRef

NewGlobalRef Создает новую глобальную ссылку на объект, на который ссылается аргумент obj. Аргумент obj может быть глобальной или локальной ссылкой. Глобальные ссылки должны быть явно удалены путем вызова DeleteGlobalRef()

и он также предоставляет локальные ссылки, которые действуют только до тех пор, пока Java передает управление C для:

Локальные ссылки действительны в течение всего времени вызова нативного метода. Они освобождаются автоматически после возврата нативного метода.

API встраивания JVM предоставляет аналогичный механизм, который позволяет закреплять объект в памяти до тех пор, пока программа C не определит, что с ним все сделано.

API расширения C Python предоставляет API, аналогичный JNI.

Заимствованная ссылка может быть изменена на принадлежащую ссылку путем вызова Py_INCREF(),

Владелец ссылки несет ответственность за звонки Py_DECREF() когда ссылка больше не нужна.

Имена python отражают тот факт, что python использует подсчет ссылок *, но API в основном такой же, как и в JNI, который основан на сборщике мусора без подсчета ссылок - у вас есть одна функция, которая закрепляет область памяти, управляемую интерпретатором и тот, который освобождает ранее закрепленную область обратно интерпретатору.

* - Python не является правильным подходом для подсчета ссылок. На той же странице "Хотя Python использует традиционную реализацию подсчета ссылок, он также предлагает детектор циклов, который работает для обнаружения циклов ссылок".

При использовании привязок с такими языками, как Java, машина другого языка содержит счетчики ссылок для каждого выделенного объекта. API должен предоставлять методы для увеличения или уменьшения счетчиков тезисов, чтобы указать машину, на которой ваша C-программа содержит ссылку на другие объекты машины. Если программа на Си не имеет ссылок на данный объект, счетчик ссылок может достигнуть 0, и другой языковой компьютер будет свободен для сбора мусора. Тем не менее, вы не сможете попросить машину выпустить данный объект.

Другие вопросы по тегам