Почему плохая практика вызывать System.gc ()? - PullRequest
308 голосов
/ 10 марта 2010

После ответа на вопрос о том, как принудительно освободить объекты в Java (парень очищал HashMap 1,5 ГБ) с помощью System.gc(), мне сказали, что это плохая практика позвоните System.gc() вручную, но комментарии были не совсем убедительными. Кроме того, никто, похоже, не осмеливался ни отрицать, ни отрицать мой ответ.

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

Я понимаю, что JVM обычно лучше вас знает, когда ему нужно восстановить память. Я также понимаю, что беспокоиться о нескольких килобайтах данных глупо. Я также понимаю, что даже мегабайты данных - это не то, что было несколько лет назад. Но все же 1,5 гигабайта? И вы знаете, как будто 1,5 ГБ данных хранятся в памяти; это не похоже на выстрел в темноте. System.gc() систематически плохо или есть какой-то момент, когда все становится хорошо?

Итак, вопрос на самом деле двойной:

  • Почему называть System.gc() плохой или плохой практикой? Действительно ли это просто подсказка JVM при определенных реализациях, или это всегда полный цикл сбора? Есть ли на самом деле реализации сборщика мусора, которые могут выполнять свою работу, не останавливая мир? Просьба пролить свет на различные утверждения, сделанные людьми в комментариях к моему ответу .
  • Где порог? никогда - это хорошая идея для звонка System.gc(), или бывают случаи, когда это приемлемо? Если да, то что это за времена?

Ответы [ 13 ]

0 голосов
/ 22 июля 2017
  1. Поскольку объекты динамически размещаются с помощью оператора new,
    вам может быть интересно, как такие объекты разрушаются и их
    память освобождена для последующего перераспределения.

  2. В некоторых языках, таких как C ++, динамически размещаемые объекты должны быть выпущенным вручную с помощью оператора удаления.

  3. Java использует другой подход; он обрабатывает освобождение для вас автоматически.
  4. Техника, которая выполняет это, называется сборкой мусора. Это работает так: когда не существует ссылок на объект, предполагается, что этот объект больше не нужен, и память, занятая объектом, может быть восстановлена. Нет явной необходимости уничтожать объекты, как в C ++.
  5. Сборка мусора происходит спорадически (если вообще происходит) во время выполнение вашей программы.
  6. Это не произойдет просто потому, что существует один или несколько объектов, которые больше не используется.
  7. Кроме того, различные реализации времени выполнения Java потребуют различные подходы к сборке мусора, но по большей части, вы не нужно думать об этом во время написания своих программ.
0 голосов
/ 30 марта 2014

мои 2 цента: я загружаю в упражнение некоторые AnimationDrawables и играю их. Я загружаю, играю, затем устанавливаю фоновый вид изображения на ноль, по одному за раз. Если я прекращаю выполнение задания, а затем быстро возвращаюсь снова, через 3 или 4 раза объем занятой памяти увеличивается слишком сильно, пока я не получу исключение нехватки памяти.

Путем явного вызова сборщика мусора после установки нулевого фона для viewview я вижу в Eclipse logcat, что память остается достаточно свободной - и в моем случае gc фактически запускается - и я больше не прекращаю работать приложение.

Очевидно, что система может решить отложить выполнение gc, но если вы более или менее знаете, как работает gc, вы можете доверять случаю, подобному моему, он будет вызван как можно скорее, потому что система замечает память используется растет и приложение собирается просить больше в систему. Я думаю, что это работает как контейнеры библиотеки c ++ std: вы получаете некоторую начальную память, и каждый раз, когда ее недостаточно, она удваивается.

Сказать, что если вам нужно вызвать его из-за неработающего или плохого кода, это необоснованный догматический способ ответить мне: особенно если вы можете программировать на языке с полным ручным управлением памятью, например, C ++, и вам необходимо соблюдать ограничение ресурсов на мобильном устройстве с таким языком, как java, без возможности освободить память вручную, вы можете быстро вспомнить множество ситуаций, в которых необходимо явно вызывать gc, особенно если у вас есть трассирующий gc, а не счетчик ссылок, код чистый и хорошо сделан.

0 голосов
/ 17 сентября 2010

По моему опыту, использование System.gc () фактически является платформенной формой оптимизации (где «платформа» - это сочетание аппаратной архитектуры, ОС, версии JVM и возможных дополнительных параметров времени выполнения, таких как доступная оперативная память), поскольку его поведение, хотя и является приблизительно предсказуемым для конкретной платформы, может (и будет) значительно различаться в зависимости от платформы.

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

Однако, будет ли это помогать или причинять боль (или ничего не делать), очень зависит от платформы (как определено выше).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...