2013-08-29 2 views
2

Насколько я понимаю, заканчивается() и GC - это два разных аспекта. GC использует метод finalize() для освобождения памяти Object. Мы не можем указать, когда произойдет GC (даже если мы явно вызываем System.gc()). Но мы можем явно вызвать finalize() для объекта.Является ли память объекта освобожденным, когда мы явно вызываем finalize() на нем?

Will the function be executed immediately(memory freed) or it waits till GC 
occurs like System.gc() call? 

Также в соответствии с Документами метод финализации никогда не вызывается более чем один раз в виртуальной машине Java для любого объекта.

Итак, что происходит, когда мы вызываем finalize() сначала, и GC происходит в более поздний момент времени.

If object memory is not freed on explicit call to object.finalize() then would't 
it being called again in the GC process violate the calling only once rule? 
+0

@duffymo не очень ... – assylias

ответ

6

У вас есть это совершенно неправильно.

Краткий ответ: finalize() - это средство для очистки ресурсов (таких как открытые файлы) непосредственно перед тем, как объект готов к сбору мусора (когда ни один объект не имеет к нему ссылки). Это может быть/не вызвано. Это на один шаг впереди освобождения памяти.

Длинный ответ:

Существует отдельный демон нить называется финализатора нить, которая отвечает за вызов завершить() метод. Завершение очереди - это очередь, в которой размещаются объекты, готовые к вызову метода finalize().

  1. Когда объект создан, JVM проверяет, переопределил ли пользователь метод finalize(). Если он тогда, он внутренне отмечает, что этот конкретный объект имеет метод finalize().

Когда объект готов к сбору мусора, поток сборщика мусора проверяет, завершен ли этот конкретный объект() из таблицы, указанной в (1).

  • 2a) Если это не так, оно отправляется для сбора мусора.

    2b) Он имеет, то он добавляется в очередь финализации. И он удаляет запись объекта из таблицы (1).

Нити финализатора продолжают опрос очереди. Для каждого объекта в очереди вызывается метод finalize(). После вызова цикла finalize() из (2) снова повторяется. Если этот объект по-прежнему не имеет сильной ссылки, то отправляется для GC. Если это то ВСЕГДА (2а) называется потому, что запись была удалена в (2b)

Basically finalize() method is only called once. 

Итак, что вопрос с выше цикла?

От (1). Это займет дополнительное время в создании объекта. Распределение памяти в Java составляет от 5 до 10 раз быстрее, чем malloc/calloc и т. Д. Все время, полученное, теряется в процедуре уведомления объекта в таблице и т. Д. Я однажды попробовал его. Создайте 100000 объектов в цикле и измерьте время, затраченное на завершение работы программы в 2 случаях: одно без finalize(), второе с finalize(). Нашли это на 20% быстрее.

Из (2b): Утечка памяти и голодание. Если объект в очереди имеет ссылки на много ресурсов памяти, тогда все эти объекты не будут освобождены, если этот объект не будет готов для GC.Если все объекты являются объектами с тяжелым весом, тогда может быть недостаток.

Из (2b): Поскольку finalize() вызывается только один раз, что делать, если в finalize() у вас была сильная ссылка на этот «объект». В следующий раз, когда finalie() объекта никогда не вызывается, может оставить объект в противоречивом состоянии.

Если внутри finalize() выбрано исключение, оно игнорируется.

Вы не знаете, когда вызывается finalize(), поскольку вы не имеете контроля над вызовом GC. Иногда может случиться так, что вы печатаете значение в finalize(), но вывод никогда не отображается, потому что ваша программа, возможно, была завершена к моменту завершения finalize().

Следовательно, избегайте его использования. Вместо того, чтобы создать метод сказать Dispose(), который будет закрывать necessory ресурсы или окончательный журнал и т.д.

+0

Таким образом, мы не можем явно назвать finali ze() на любом объекте, и даже если мы это сделаем, это будет выполняться только тогда, когда произойдет GC. Это правильно? –

+0

Если вы хотите позвонить вам, всегда вызывайте его. Но это нецелесообразно. И если вы его назовете, он будет выполнен как любой другой вызов метода. После этого GC-вызов будет позже (хотя он может появиться или не появится). Читайте выше для получения дополнительной информации – Jatin

+0

@Jatin - +1 (особенно для первого предложения), но, пожалуйста, просмотрите мое редактирование. Вы описали * what * finalize(), я описал * почему * кто-то может подумать, что он в этом нуждается. – kdgregory

1

As per docs:

Метод финализации никогда не вызывается более чем один раз в виртуальной машине Java для любого объекта.

Однако вы не можете заставить GC работать, вы можете просто попросить его через System.gc(). Поэтому лучший подход заключается в том, что при переопределении код ресурса освобождается от finalize().

+0

все еще зависит от jvm, но это в основном ответ –

1

Ответы в Object.Finalize API

1) GC звонки завершить(), чтобы завершить() и GC НЕ два различных аспекта

2) Вы не должны вызывать завершить вручную, но если вы делаете он не будет не освободит всю память, и это не повлияет на поведение GC

3) Говорят, что это гарантирует, что GC не будет вызывать завершения дважды, наши звонки не считаются

 Смежные вопросы

  • Нет связанных вопросов^_^