Java и выполнение финализации вручную - PullRequest
16 голосов
/ 26 августа 2008

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

Это будет примерный пример:

MyObject m = new MyObject();

m.finalize();

m = null;

System.gc()

Будет ли явный вызов finalize() заставить сборщик мусора JVM не запускать метод finalize() для объекта m?

Ответы [ 3 ]

29 голосов
/ 26 августа 2008

В соответствии с этой простой тестовой программой JVM по-прежнему будет вызывать finalize (), даже если вы ее явно вызвали:

private static class Blah
{
  public void finalize() { System.out.println("finalizing!"); }
}

private static void f() throws Throwable
{
   Blah blah = new Blah();
   blah.finalize();
}

public static void main(String[] args) throws Throwable
{
    System.out.println("start");
    f();
    System.gc();
    System.out.println("done");
}

Вывод:

1007 * начать * финализации!
финализации!
сделано

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

7 голосов
/ 20 декабря 2013

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

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

Цитата: "После того, как метод finalize был вызван для объекта, никакие дальнейшие действия не предпринимаются, пока виртуальная машина Java снова не определит, что больше нет никаких средств, к которым этот объект может быть доступен любому потоку, который все еще умер, включая возможные действия других объектов или классов, которые готовы к финализации, и в этот момент объект может быть отброшен. "из Java API Doc на java.Object.finalize ();

Для подробного объяснения вы также можете проверить: javabook.computerware

1 голос
/ 26 августа 2008

Метод finalize никогда не вызывается JVM более одного раза для любого данного объекта. Вы не должны полагаться на завершение в любом случае, потому что нет никакой гарантии, что он будет вызван. Если вы вызываете finalize, потому что вам нужно выполнить код очистки, то лучше поместить его в отдельный метод и сделать его явным, например:

public void cleanUp() {
  .
  .
  .
}

myInstance.cleanUp();
...