Собирается ли мусор примитивных типов в Android?

Я знаю, что это может быть глупый вопрос, но мой опыт больше связан с C++ и управлением собственной памятью.

В настоящее время я сокращаю каждое отдельное выделение, которое я могу из одной из моих игр, чтобы попытаться уменьшить частоту сборки мусора и воспринимаемое «запаздывание», поэтому для каждой переменной, которую я создаю, которая является объектом (например, String и Rect), я я удостоверяюсь, что создаю его заранее в своем конструкторе, а не создаю временные переменные в простых 10-строчных функциях... (надеюсь, это имеет смысл)

В любом случае, сегодня вечером я работал еще немного, и я понял, что могу быть совершенно неправ в своем предположении о сборке мусора, а примитивные типы (int, boolean, float) - это эти переменные примитивного типа, которые я создаю в 10-строчной функции, которая вызывается 20 раз в секунду, добавляя к моей проблеме сборки мусора?

Итак, год назад каждые несколько секунд я видел сообщение в logcat, например

Сборщик мусора освободил 4010 объектов / 484064 байта за 101 мс.

Теперь я вижу это сообщение каждые 15-90 секунд или около того...

Итак, перефразируя мой вопрос: включены ли примитивные типы (int, float, boolean и т. д.) при просмотре этого сообщения?


person snctln    schedule 19.03.2010    source источник


Ответы (3)


Примитивные типы не являются объектами, поэтому они не вызывают сборку мусора. Однако вам нужно быть очень осторожным, потому что из-за упаковки примитивный тип может легко стать объектом без вашего явного указания.

Например, если вам нужна HashMap‹> целочисленных ключей, вы должны использовать HashMap. Обратите внимание: поскольку «int» не является объектом, его нельзя использовать в контейнере. Integer — это объектная версия примитива int. Когда вы пишете такой код, для вас автоматически создается объект Integer:

HashMap<Integer, Object> map = new HashMap<Integer, Object>();
int someNum = 12345;    // no object created.
map.put(someNum, null); // Integer object created.

Обратите внимание, что то же самое произойдет, если вы не используете дженерики, но даже более скрыто:

HashMap map = new HashMap();
int someNum = 12345;    // no object created.
map.put(someNum, null); // Integer object created.

В этой конкретной ситуации вы можете использовать класс Android SparseArray, который представляет собой контейнер примитивных целочисленных ключей.

person hackbod    schedule 19.03.2010

Кажется, что нет. Похоже, что примитивы помещаются в стек в Java, а не в кучу, и только объекты собираются мусором. Я нашел много коротких ссылок на это, посмотрите Википедию. Для более подробного чтения см. статью о реализации сборки мусора JVM, в которой несколько более недвусмысленно объясняется, что примитивы хранятся в физически отдельных местах памяти, поэтому они не включаются по ошибке в сборку мусора здесь. Если вам хочется бегло просмотреть, на странице 4 это объяснено наиболее прямо.

вот конкретные потоки Android, в которых указывается gc сканирует только указатели и как проверит, что

person jqpubliq    schedule 19.03.2010
comment
Android не запускает стандартную JVM на основе стека, у него есть собственная виртуальная машина на основе регистров. - person mikerobi; 19.03.2010

[Примечание: у меня еще нет полных прав комментирования, поэтому я добавляю это как отдельный ответ.]

Похоже, что примитивы помещаются в стек в Java, а не в кучу, и только объекты собираются мусором.

Это не совсем точно. Примитивы могут храниться в локальных переменных, а также в виде статических или экземплярных полей классов. В последнем случае они действительно хранятся в куче, но, что важно, они не имеют собственной «жизни» и, в частности, не собираются отдельно от объекта, в котором они содержатся.

Android не запускает стандартную JVM на основе стека, у него есть собственная виртуальная машина на основе регистров.

Это верное утверждение, но оно также немного вводит в заблуждение и выходит за рамки исходного вопроса. На самом деле, когда один метод вызывает другой (и так далее), кадры активации этих методов сохраняются в стеке в реализации Dalvik. Разница в том, что если рассматривать кадр активации отдельно, то кадры активации Dalvik не содержат внутри стека переменного размера. В этом отношении то, как Dalvik упорядочивает фреймы активации, больше похоже на то, как они обрабатываются для традиционных C-подобных языков (таких как C или C++).

person danfuzz    schedule 05.05.2011
comment
подождите, пока они не получат N.P.E. из-за отсутствия тривиального конструктора по умолчанию для auto в вызове метода, а затем попробуйте преследовать его, используя стирание типа в качестве единственной подсказки - основной вопрос ope связан с созданием скрытых объектов и GC. которым довольно сложно управлять для парадигмы программирования в стиле «C», где можно выполнить то, что делает «D» с ~ this ... хотя единственный эффективный подход - использовать синхронизированное ключевое слово и повторно использовать obj ref (который получит много воя от признанных традиционалистов Java), так что действительно то, что нужно сделать OP, это прочитать Hans-J. Комментарии Бема в gc.h - person Nicholas Jordan; 25.11.2011