Looking for java Keywords? Try Ask4Keywords

Java Language Pitfall - Calling System.gc () неэффективен


пример

Это (почти всегда) плохая идея вызвать System.gc() .

Javadoc для метода gc() указывает следующее:

«Вызов метода gc предполагает, что виртуальная машина Java тратит усилия на повторное использование неиспользуемых объектов, чтобы сделать память, которую они в настоящее время занимают, для быстрого повторного использования. Когда управление возвращается из вызова метода, виртуальная машина Java приложила все усилия для восстановления пространство от всех отброшенных объектов ».

Из этого можно выделить пару важных моментов:

  1. Использование слова «предлагает», а не (скажем) «говорит» означает, что JVM может игнорировать это предложение. Поведение JVM по умолчанию (последние выпуски) заключается в том, чтобы следовать этому предложению, но это можно переопределить, установив -XX:+DisableExplicitGC при запуске JVM.

  2. Фраза «лучшее усилие для освобождения пространства от всех отброшенных объектов» подразумевает, что вызов gc вызовет «полную» сборку мусора.

Итак, почему вызывает System.gc() плохую идею?

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

Во-вторых, полная сборка мусора может нарушить свойства «локальности» объектов, которые не собираются. Объекты, которые распределены одним и тем же потоком примерно в одно и то же время, как правило, распределяются близко друг к другу в памяти. Это хорошо. Объекты, которые распределены одновременно, скорее всего, будут связаны; т.е. ссылаться друг на друга. Если ваше приложение использует эти ссылки, то вероятность того, что доступ к памяти будет быстрее из-за различных эффектов кэширования памяти и страницы. К сожалению, полная сборка мусора, как правило, перемещает объекты вокруг, так что объекты, которые когда-то были близки, теперь раздвинуты.

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

На самом деле, лучшая стратегия - позволить JVM решить, когда запускать GC и какую коллекцию запускать. Если вы не вмешиваетесь, JVM выберет время и тип сбора, который оптимизирует пропускную способность или минимизирует время паузы GC.


Сначала мы говорили «... (почти всегда) плохая идея ...». На самом деле есть несколько сценариев, где это может быть хорошей идеей:

  1. Если вы выполняете единичный тест для некоторого кода, который чувствителен к сборке мусора (например, что-то включает финализаторы или слабые / мягкие / фантомные ссылки System.gc() может потребоваться вызов System.gc() .

  2. В некоторых интерактивных приложениях могут быть определенные моменты времени, когда пользователю не будет делаться пауза в сборе мусора. Одним из примеров является игра, в которой есть естественные паузы в «игре»; например, при загрузке нового уровня.