Подтвердить что ты не робот

Почему финализаторы имеют "серьезный штраф за исполнение"?

Эффективная Java говорит:

Для использования финализаторов существует серьезное ограничение производительности.

Почему медленнее уничтожать объект с помощью финализаторов?

4b9b3361

Ответ 1

Из-за того, как работает сборщик мусора. Для производительности большинство Java-GC используют копировальный коллектор, где короткие объекты распределяются в блок памяти "eden", а когда это время для создания этого поколения объектов, GC просто нужно скопировать объекты, которые все еще "живы" для более постоянного пространства для хранения, а затем он может стереть (освободить) весь блок памяти "eden" сразу. Это эффективно, потому что большинство Java-кода создадут много тысяч экземпляров объектов (вложенные примитивы, временные массивы и т.д.) Со временем жизни всего несколько секунд.

Если у вас есть финализаторы в миксе, GC не может просто стереть сразу целое поколение. Вместо этого необходимо выяснить все объекты в этом поколении, которые должны быть завершены, и поставить их в очередь на поток, который фактически выполняет финализаторы. В то же время GC не может завершить очистку объектов эффективно. Таким образом, это либо должно держать их в живых дольше, чем они должны быть, либо откладывать сбор других объектов, или и то, и другое. Кроме того, у вас есть произвольное время ожидания фактического выполнения финализаторов.

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

Ответ 2

Фактически столкнувшись с одной из таких проблем:

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

Это, конечно, в дополнение к другим многим причинам не использовать финализаторы, описанные в "Эффективной Java".

Ответ 3

Моя мысль такова: Java - это сборник мусора, который освобождает память на основе собственных внутренних алгоритмов. Каждый так часто GC сканирует кучу, определяет, какие объекты больше не ссылаются, и де-выделяет память. Финализатор прерывает это и заставляет освобождение памяти за пределами цикла GC, что может вызвать неэффективность. Я считаю, что лучшие практики - использовать финализаторы только тогда, когда АБСОЛЮТНО необходимо, например, освободить дескрипторы файлов или закрыть соединения DB, которые должны выполняться детерминистически.

Ответ 4

Я просто взял свою копию "Эффективная Java" со своего стола, чтобы увидеть, о чем он говорит.

Если вы прочитали главу 2, раздел 6, он подробно описывает различные хиты производительности.

You can't know when the finalizer will run, or even if it will at all. Because those resources may never be claimed, you will have to run with fewer resources.

Я бы рекомендовал прочитать весь раздел - он объясняет вещи намного лучше, чем я могу попугать здесь.

Ответ 5

Если вы внимательно прочитаете документацию finalize(), вы заметите, что финализаторы позволяют объекту предотвратить сбор GC.

Если финализатор отсутствует, объект просто может быть удален и больше не нужен. Но если есть финализатор, он должен быть проверен впоследствии, если объект снова не стал "видимым".

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

Ответ 6

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