Почему финализаторы имеют “серьезную потерю производительности”?

Эффективный Java говорит:

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

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

24
задан Martijn Courteaux 18 May 2010 в 18:59
поделиться

6 ответов

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

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

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

23
ответ дан 28 November 2019 в 23:47
поделиться

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

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

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

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

2
ответ дан 28 November 2019 в 23:47
поделиться

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

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

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

10
ответ дан 28 November 2019 в 23:47
поделиться

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

1
ответ дан 28 November 2019 в 23:47
поделиться

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

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

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

1
ответ дан 28 November 2019 в 23:47
поделиться

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

0
ответ дан 28 November 2019 в 23:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: