finalize () - это средство для выполнения последнего бита кода непосредственно перед тем, как объект будет готов для сборки мусора (когда у объекта нет строгой ссылки на него).
Так, когда это должно использоваться?
Только в настоящих двух случаях:
- В качестве обеспечения безопасности, чтобы убедиться, что некоторые службы закрыты или некоторые
желаемое окончательное изменение сделано. Например, класс InputStream использует его
закрыть поток ввода-вывода. Вот например ты сделал
экземпляр BufferedInputStream. Вручную после его использования
предположим закрыть () это. Но потому что можно забыть сделать это,
finalize () действует как сеть безопасности для закрытия () потока.
- Несмотря на то,
используя родные. Потому что сборщик мусора не имеет никакого контроля над родным
объекты finalize () могут использоваться как средство для его восстановления.
Кроме двух вышеупомянутых случаев, никогда не используйте его. Чтобы понять почему? нам нужно понять функционирование и жизненный цикл объекта.
Введение: существует отдельный поток демона, называемый потоком финализатора, который отвечает за вызов метода finalize (). Очередь финализации - это очередь, в которую помещаются объекты, готовые для вызова метода finalize ().
- При создании объекта JVM проверяет, есть ли у объекта метод finalize (). Если это так, то он внутренне отмечает, что этот конкретный объект имеет метод finalize ().
Когда объект готов к сборке мусора, поток сборщика мусора проверяет, имеет ли этот конкретный объект finalize () из таблицы, упомянутой в (1).
2a) Если это не так, то он отправляется на сборку мусора.
2b) Имеет, затем добавляется в очередь завершения. И он удаляет запись объекта из таблицы (1).
Поток финализатора продолжает опрашивать очередь. Для каждого объекта в очереди вызывается его метод finalize (). После вызова finalize () цикл из (2) снова повторяется. Если этот объект по-прежнему не имеет строгой ссылки, то отправляется на GC. Если
тогда он ВСЕГДА (2a) вызывается, потому что запись была удалена в (2b)
Basically finalize() method is only called once.
Так в чем же проблема с вышеуказанным циклом?
Из (1). Это займет дополнительное время в создании объекта. Выделение памяти в Java в 5–10 раз быстрее, чем malloc / calloc и т. Д. Все полученное время теряется при процедуре записи объекта в таблицу и т. Д. Я однажды попробовал это сделать. Создайте 100000 объектов в цикле и измерьте время, необходимое для завершения программы в 2 случаях: один без finalize (), второй с finalize (). Найдено на 20% быстрее.
Из (2b): Утечка памяти и голод. Если объект в очереди имеет ссылки на большое количество ресурсов памяти, то все эти объекты не будут освобождены, если этот объект не готов к GC. Если все объекты являются объектами с большим весом, тогда может возникнуть дефицит.
From (2b): Поскольку finalize () вызывается только один раз, что если в finalize () у вас есть сильная ссылка на этот объект. В следующий раз, когда finalie () объекта никогда не вызывается, следовательно, он может оставить объект в несогласованном состоянии.
Если внутри finalize () генерируется исключение, оно игнорируется.
Вы не знаете, когда вызывается finalize (), поскольку вы не можете контролировать, когда вызывается GC. Иногда может случиться так, что вы печатаете значения в finalize (), но вывод никогда не отображается, потому что ваша программа могла завершиться к моменту вызова finalize ().
Поэтому избегайте его использования. Вместо этого создайте метод скажем dispose (), который закроет необходимые ресурсы или для окончательного журнала и т. Д.
полный пост на нем . Я надеюсь, что это очищает.