Влияние производительности финализаторов на JVM - PullRequest
7 голосов
/ 02 июня 2010

Согласно этому посту , в .Net,

Финализаторы на самом деле даже хуже.Помимо того, что они запаздывают (что действительно является серьезной проблемой для многих видов ресурсов), они также менее мощны, поскольку могут выполнять только поднабор операций, разрешенных в деструкторе (например, финализатор не может надежно использовать другие объекты, тогда какдеструктор может), и даже при записи в это подмножество финализаторов крайне сложно писать правильно.А сбор финализируемых объектов стоит дорого: каждый финализуемый объект и потенциально огромный граф объектов, достижимых из него, продвигается до следующего поколения GC, что делает его более дорогим для сбора при большом кратном числе.* Применимо ли это к JVM в целом и к HotSpot в частности?

Ответы [ 4 ]

4 голосов
/ 02 июня 2010

Здесь - явное утверждение 2004 года:

Объекты с финализаторами (те, которые имеют нетривиальный метод finalize()) имеют значительные накладные расходы по сравнению с объектами без финализаторов и должны использоваться экономно. Завершаемые объекты медленнее распределяются и медленнее собираются. Во время выделения JVM должна зарегистрировать любые объекты финализируемого объекта в сборщике мусора, и (по крайней мере в реализации HotSpot JVM) объекты финализируемого объекта должны следовать более медленному пути выделения, чем большинство других объектов. Точно так же финализуемые объекты собирать медленнее. Требуется по крайней мере два цикла сборки мусора (в лучшем случае), прежде чем финализуемый объект может быть возвращен, и сборщик мусора должен выполнить дополнительную работу для вызова финализатора. В результате вы тратите больше времени на выделение и сбор объектов и повышаете нагрузку на сборщик мусора, поскольку память, используемая недостижимыми завершаемыми объектами, сохраняется дольше. Добавьте к этому тот факт, что финализаторы не гарантированно будут работать в любой предсказуемый период времени или даже вообще, и вы увидите, что существует относительно немного ситуаций, для которых финализация является правильным инструментом для использования.

3 голосов
/ 02 июня 2010

Вот некоторые избранные цитаты из Effective Java 2nd Edition: Пункт 7: Избегайте финализаторов :

Финализаторы непредсказуемы, часто опасны и, как правило, не нужны . Их использование может вызвать нестабильное поведение, плохую производительность и проблемы с переносимостью. У финализаторов мало действительных применений, [...] как правило, вам следует избегать финализаторов.

Вы действительно должны убедиться, что на самом деле вам действительно нужны финализаторы; большую часть времени вы не делаете.

Программисты C ++ не должны думать о финализаторах как о Java-аналоге деструкторов C ++. В C ++ деструкторы являются обычным способом восстановления ресурсов, связанных с объектом, необходимого аналога конструкторам. В Java сборщик мусора восстанавливает хранилище, связанное с объектом, когда он становится недоступным, не требуя особых усилий со стороны программиста. Деструкторы C ++ также используются для восстановления других ресурсов памяти. В Java для этой цели обычно используется блок try-finally.

Семантика при вызове финализаторов также важна:

JLS 12.6 Завершение экземпляров класса

Язык программирования Java не определяет, как скоро будет вызываться finalizer [... ни], какой поток вызовет финализатор для любого данного объекта. [...] Если во время финализации генерируется неперехваченное исключение, оно игнорируется, и финализация этого объекта завершается. (JLS 12.6.2) Вызовы финализатора не заказаны

Более того, единственный механизм запуска финализатора по требованию сломан. Следующие цитаты взяты из Effective Java 2nd Edition:

[...] Единственные методы, которые утверждают, что гарантируют завершение, это System.runFinalizersOnExit и его злой близнец Runtime.runFinalizersOnExit. Эти методы смертельно несовершенны и устарели.

Блох пошел дальше, чтобы прокомментировать штраф за исполнение (выделение его):

О, и есть еще одна вещь: есть серьезное снижение производительности за использование финализаторов . На моей машине время создания и уничтожения простого объекта составляет около 5,6 нс. Добавление финализатора увеличивает время до 2400 нс. Другими словами, создание и уничтожение объектов с помощью финализаторов примерно в 430 раз медленнее.

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

Книга объясняет редкие сценарии, при которых допустимо использование финализаторов. Пропуск этих цитат из этого ответа является преднамеренным.

1 голос
/ 02 июня 2010

В Java очень похожий механизм для финализаторов. Вот хорошая статья о финализаторах: http://www.javaworld.com/javaworld/jw-06-1998/jw-06-techniques.html

Общее правило в Java - не используйте их.

0 голосов
/ 30 января 2014

finalize () Вызывается сборщиком мусора на объекте, когда сборщик мусора определяет, что больше нет ссылок на объект. Подкласс переопределяет метод finalize для удаления системных ресурсов или для другой очистки.

Не используйте финализаторы, в основном потому, что они непредсказуемы, а мы не знаем когда будет выполнено: «не пытайтесь быть умнее, чем JVM»

...