Родная библиотека C ++ - кому и как освобождать память? - PullRequest
4 голосов
/ 22 сентября 2011

Это про Android.Ситуация:

Библиотека C ++ и классы-оболочки Java, а также встроенные функции (JNI) для работы с классами C ++ из библиотеки.Когда обычному Java-коду нужен объект C ++, он создает соответствующий объект-оболочку Java, который создает объект C ++ через встроенную функцию и запоминает указатель на собственный объект в переменной 'long'.Во всех последующих действиях оболочка дает этот указатель на встроенные функции и т. Д.

Проблема:

Как освободить все выделенные объекты C ++ в конце?В настоящее время каждый класс-оболочка имеет метод 'finalize', в котором он вызывает нативную функцию для освобождения объекта C ++, но Android не гарантирует вызов 'finalize'!С другой стороны, обычно библиотека C ++ не имеет представления о том, сколько и какие типы объектов C ++ выделяются Java-кодом.

Что произойдет с оставшейся выделенной памятью после завершения работы нашего Java-приложения, Android автоматически выйдетвся куча, используемая из нативной библиотеки, когда ОС выгружает библиотеку?

Ответы [ 3 ]

3 голосов
/ 23 сентября 2011

В конце времени жизни процесса вся память процесса (как кучи Java, так и C ++) будет освобождена и восстановлена ​​системой. Однако одно дело - закрытие активности Android не обязательно заканчивает процесс. Я не уверен, какова там политика завершения процесса.

С другой стороны, полагаться на сборку мусора и finalize () для меня звучит солидно. Вы утверждаете - «Android не гарантирует finalize()». У вас есть цитата для этого? Потому что, если он идет с заявлением об отказе «когда объект освобождается как часть завершения процесса ...», тогда мы все еще в порядке.

И если вы супер-параноик, вы можете написать свою собственную обертку malloc () / free () / realloc (), сохранить список всех выделенных объектов и ввести функцию очистки, которая обходит список и освобождает их все. Содержащие объекты Java, однако, могут закончиться в странном состоянии зомби, где память была освобождена из-под них. Это сложное предложение, в котором очень легко ошибиться. Так что я бы еще сказал - верь в сборщика мусора. Отсутствие этого будет ... тревожным.

1 голос
/ 23 сентября 2011

Из-за различий в парадигмах, вы должны включить явное уничтожение в ваши объекты Java, которые реализованы под капотом с использованием ресурсов C ++. Так что close() или другой такой метод. Та же проблема возникает с JNI, поэтому ответы на эти вопросы будут применяться к вам:

Заставить Java вызывать мой деструктор C ++ (JNI)

Что касается проблемы с памятью при закрытии, на мой взгляд, лучше всего не полагаться на это. Если вы доберетесь до чистого состояния, valgrind и другие могут убедиться, что вы не протекаете.

Но с технической точки зрения - поскольку Android основан на Linux, я бы предположил, что он работает как обычно и освободит всю память, когда процесс закроется. Использование этого может заставить вашу программу завершиться быстрее, чем явное освобождение памяти (только для экспертов, которые используют другие методы, чтобы гарантировать правильность программы и не просачиваться во время выполнения).

0 голосов
/ 29 сентября 2011

Мы используем JNI, и у нас была такая проблема

На самом деле проблема заключалась в том, что мы перегружали finalize () для очистки. Мы решили наши проблемы, удалив finalize () и создав вместо него clean (). Этот метод clean () вызывает функцию JNI, которая выполняет соответствующее удаление (и на всякий случай устанавливает для указателей C ++ значение null). Мы вызываем clean () так же, как и в C ++, с delete (например, когда переменная выходит из области видимости).

Это сработало для нас. Я надеюсь, что это работает для вас. Удачи!

...