Мне нужно знать, когда finalize()
метод вызывается в JVM
. Я создал тестовый класс, который записывает в файл при finalize()
вызове метода путем его переопределения. Это не выполнено. Кто-нибудь может сказать мне причину, почему это не выполняется?
330
finalize()
и сборка мусора не имеет никакого влияния.Ответы:
В общем, лучше не полагаться на
finalize()
уборку и т. Д.Согласно Javadoc (который стоило бы прочитать), это:
Как отметил Иоахим, это может никогда не произойти в жизни программы, если объект всегда доступен.
Кроме того, сборщик мусора не гарантированно работает в любое конкретное время. В общем, то, что я пытаюсь сказать, это
finalize()
, вероятно, не лучший метод для использования в целом, если нет необходимости в чем-то конкретном.источник
finalize
было бы полезно?finalize()
Метод на для основного класса вызывается , когда >> << экземпляр класса является сбор мусора, не тогда , когда основной метод завершается. И, кроме того, главный класс может быть собран мусором до завершения приложения; например, в многопоточном приложении, где «основной» поток создает другие потоки, а затем возвращает. (На практике потребуется нестандартный загрузчик классов ....)finalize
Метод вызывается , когда объект собирается получить мусор. Это может произойти в любое время после того, как он получил право на сборку мусора.Обратите внимание, что вполне возможно, что объект никогда не получает мусор (и, следовательно
finalize
, никогда не вызывается). Это может произойти, когда объект никогда не становится подходящим для gc (потому что он доступен в течение всего времени жизни JVM) или когда фактически не выполняется сборка мусора между моментом, когда объект становится приемлемым, и временем, когда JVM прекращает работу (это часто происходит с простыми тестовые программы).Есть способы заставить JVM работать
finalize
с объектами, которые еще не были вызваны, но их использование тоже не очень хорошая идея (гарантии этого метода также не очень сильны).Если вы полагаетесь на
finalize
правильную работу вашего приложения, то вы делаете что-то не так.finalize
следует использовать только для очистки (обычно не Java) ресурсов. И это именно потому, что JVM не гарантирует, чтоfinalize
когда-либо вызывается на любом объекте.источник
Closable
интерфейс (и идея, лежащая в его основе), вероятно, то, что вам нужно:.close()
закройте / отмените ресурс и потребуйте, чтобы пользователь вашего класса вызвал его в нужное время. Вы , возможно , хотите добавитьfinalize
метод «просто быть сохранить», но это будет скорее инструмент отладки , чем фактическое исправление (потому что это не достаточно надежным).System.gc()
чтобы вызвать FileInputStream :: finalize (), затем я мог переместить файл.цитируется с: http://www.janeg.ca/scjp/gc/finalize.html
Вы также можете проверить эту статью:
источник
Метод Java
finalize()
не является деструктором и не должен использоваться для обработки логики, от которой зависит ваше приложение. Спецификация Java утверждает, что нет гарантии, чтоfinalize
метод вызывается вообще во время работы приложения.Вероятно, вам нужно сочетание
finally
и метод очистки, как в:источник
Проверьте Effective Java, 2-е издание, стр. 27. Пункт 7: Избегайте финализаторов
Чтобы завершить ресурс, используйте вместо этого try-finally:
источник
Метод finalize будет вызван после того, как GC обнаружит, что объект более недоступен, и до того, как он фактически освободит память, используемую объектом.
Если объект никогда не станет недоступным,
finalize()
его никогда не вызовут.Если GC не работает, то
finalize()
никогда не может быть вызван. (Обычно GC запускается только тогда, когда JVM решает, что мусора, вероятно, достаточно, чтобы оно того стоило.)Может потребоваться более одного цикла GC, прежде чем GC определит, что определенный объект недоступен. (Java GC, как правило, являются сборщиками поколений ...)
Как только GC обнаруживает, что объект недоступен и завершен, он помещается в очередь завершения. Завершение обычно происходит асинхронно с обычным GC.
(Спецификация JVM фактически позволяет JVM никогда не запускать финализаторы ... при условии, что она не освобождает пространство, используемое объектами. JVM, который был реализован таким образом, будет поврежден / бесполезен, но если это поведение "разрешено" .)
В результате неразумно полагаться на завершение, чтобы делать то, что должно быть сделано в определенные сроки. Это «лучшая практика» - не использовать их вообще. Должен быть лучший (то есть более надежный) способ сделать то, что вы пытаетесь сделать в
finalize()
методе.Единственное законное использование для финализации - очистить ресурсы, связанные с объектами, которые были потеряны кодом приложения. Даже тогда вы должны попытаться написать код приложения, чтобы он не терял объекты в первую очередь. (Например, используйте Java 7+ try-with-resources, чтобы
close()
всегда вызывать ...)Трудно сказать, но есть несколько возможностей:
источник
Поскольку существует неопределенность в вызове метода finalize () из JVM (не уверен, будет ли выполнен finalize (), который переопределяется, будет или нет), для целей изучения лучший способ наблюдать за тем, что происходит при вызове finalize (), состоит в том, чтобы заставить JVM вызывать сборщик мусора командой
System.gc()
.В частности, finalize () вызывается, когда объект больше не используется. Но когда мы пытаемся вызвать его, создавая новые объекты, нет уверенности в его вызове. Поэтому для определенности мы создаем
null
объект,c
который, очевидно, не будет использоваться в будущем, поэтому мы видимc
вызов объекта finalize.пример
Вывод
Примечание. Даже после печати до 70 и после того, как объект b не используется в программе, существует неопределенность, что b очищается или не удаляется JVM, так как «Вызванный метод финализации в классе Bike ...» не печатается.
источник
System.gc();
не является гарантией того, что сборка мусора действительно будет запущена.finalize распечатает счет для создания класса.
основной
Как вы видете. Следующий вывод показывает, что gc был выполнен первый раз, когда счетчик классов равен 36.
источник
В последнее время, борясь с методами финализатора (чтобы избавиться от пулов соединений во время тестирования), я должен сказать, что финализатору не хватает многих вещей. Используя VisualVM для наблюдения, а также используя слабые ссылки для отслеживания реального взаимодействия, я обнаружил, что в среде Java 8 верно следующее: Oracle JDK, Ubuntu 15):
Последняя мысль
Метод Finalize ненадежен, но может использоваться только для одной цели. Вы можете убедиться, что объект был закрыт или утилизирован до того, как он был собран мусором, что позволяет реализовать отказоустойчивый объект, если объекты с более сложным жизненным циклом, включающим действие с истекшим сроком службы, обрабатываются правильно. Это единственная причина, по которой я могу придумать, стоит того, чтобы ее переопределить.
источник
Объект получает право на сборку мусора или сборщик мусора, если он недоступен из каких-либо активных потоков или статических ссылок, другими словами, вы можете сказать, что объект получает право на сборку мусора, если все его ссылки равны нулю. Циклические зависимости не считаются ссылками, поэтому, если у объекта A есть ссылка на объект B, а у объекта B есть ссылка на объект A, и у них нет никакой другой активной ссылки, тогда и объекты A, и B будут иметь право на сборку мусора. Обычно объект получает право на сборку мусора в Java в следующих случаях:
источник
final
поле объекта используется многократно во время медленного вычисления, и объект никогда не будет использоваться после этого, будет ли объект сохранен живым до тех пор, пока исходный код не запросит поле, или JIT может скопировать поле в временная переменная, а затем отказаться от объекта до вычисления?GC.KeepAlive()
функция, которая ничего не делает, кроме как заставить GC предположить, что она может использовать объект, но я не знаю такой функции в Java. Можно использоватьvolatile
переменную для этой цели, но использование переменной исключительно для этой цели может показаться расточительным.FinalizerReference
, так что ему не нужен цикл GC, чтобы выяснить, что нет Ссылки. Синхронизация достаточна для того, чтобы обеспечить связь «до того как случится» ; поскольку финализация может (на самом деле) выполняться в другом потоке, она все равно формально необходима в любом случае. Java 9 собирается добавитьReference.reachabilityFence
...Finalize
будет вызван только один, если JIT создаст код, который сделал это напрямую. Можно ли ожидать код синхронизации для объектов, которые ожидают использования только в одном потоке? Если объект выполняет какое-либо действие, которое необходимо отменить перед тем, как его прекратить (например, открытие соединения с сокетом и получение исключительного использования для ресурса на другом конце), если финализатор закроет соединение, пока код все еще использует сокет, будет катастрофой , Было бы нормально, чтобы код использовал синхронизацию ...Метод финализации не гарантирован. Этот метод вызывается, когда объект получает право на сборщик мусора. Есть много ситуаций, когда объекты не могут быть собраны мусором.
источник
Иногда, когда он уничтожен, объект должен совершить действие. Например, если объект имеет не-Java-ресурс, такой как дескриптор файла или шрифт, вы можете проверить, что эти ресурсы освобождены, прежде чем уничтожать объект. Для управления такими ситуациями java предлагает механизм, называемый «финализация». Завершив его, вы можете определить конкретные действия, которые происходят, когда объект собирается удалить из сборщика мусора. Чтобы добавить финализатор в класс, просто определите метод finalize () . Время выполнения Java вызывает этот метод всякий раз, когда он собирается удалить объект этого класса. В методе финализации () вы указываете действия, которые должны быть выполнены перед уничтожением объекта. Сборщик мусора периодически ищет объекты, которые больше не ссылаются ни на какое запущенное состояние или косвенно на любой другой объект со ссылкой. Перед освобождением актива среда выполнения Java вызывает метод finalize () для объекта. finalize () имеет следующую общую форму:
С помощью защищенного ключевого слова доступ к finalize () по коду вне его класса запрещен. Важно понимать, что finalize () вызывается непосредственно перед сборкой мусора. Например, он не вызывается, когда объект покидает область видимости. Это означает, что вы не можете знать, когда или если будет выполнено finalize () . В результате программа должна предоставлять другие средства для освобождения системных ресурсов или других ресурсов, используемых объектом. Вы не должны полагаться на finalize () для нормального запуска программы.
источник
Класс, в котором мы переопределяем метод финализации
Возможности вызова метода финализации
когда память перегружена объектами дампа, gc вызовет метод finalize
запустите консоль, где вы не найдете часто вызываемого метода finalize, когда память перегружается, вызывается метод finalize.
источник
Источник
источник
finalize()
вызывается как раз перед сборкой мусора. Он не вызывается, когда объект выходит из области видимости. Это означает, что вы не можете знать, когда или дажеfinalize()
будет ли выполнено.Пример:
Если ваша программа завершится до того, как произойдет сборщик мусора,
finalize()
она не будет выполнена. Поэтому его следует использовать в качестве процедуры резервного копирования для обеспечения надлежащей обработки других ресурсов или для приложений специального назначения, а не в качестве средства, которое ваша программа использует в своей нормальной работе.источник
Как указано в https://wiki.sei.cmu.edu/confluence/display/java/MET12-J.+Do+not+use+finalizers ,
источник
Попробуйте запустить эту Программу для лучшего понимания
источник