Что произошло внутри (JVM) при вызове метода System.gc () или finalize ()? - PullRequest
5 голосов
/ 21 мая 2009

Что произошло внутри (JVM) при вызове метода System.gc () или finalize ()?

Это действительно сбор мусора или снижение производительности?

Ответы [ 6 ]

8 голосов
/ 21 мая 2009

То, что происходит при вызове System.gc () , зависит от JVM. JVM рассматривает этот вызов как предложение о том, что сейчас самое время запустить сборщик мусора, поэтому не зависите от него.

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

3 голосов
/ 21 мая 2009

Если вы хотите узнать о внутренностях сборки мусора, вам следует прочитать Техническое описание Hotspot Memory Management от Sun.

1 голос
/ 21 мая 2009

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

В последнем вопросе не должно быть "or". Это сборщик мусора и снижение производительности.

Обычно вам вообще не нужно беспокоиться о gc, потому что он действительно хорошо для вас работает. Существуют сценарии использования, в которых вы хотите избавиться от множества объектов в определенный момент времени; Тогда это возможно.

0 голосов
/ 09 апреля 2014

Да System.gc (); при необходимости вызовет метод finalize (). открытый класс TestGarbageCollection {

public static void main(String[] args) {
    while (true) {
        TestClass s = new TestClass();
        s.display();
        System.gc();
    }
}

}

открытый класс TestClass {

public TestClass() {
    System.out.println("constructor");
}

public void display() {
    System.out.println("display");
}
@Override
public void finalize() {
    System.out.println("destructor");
}

}

Это вызовет метод finalize (). независимо от того, переопределите ли вы метод finalize или нет, будет вызван метод локального класса или Object.

0 голосов
/ 17 апреля 2012

System.gc () очищает память и использует finalize (), чтобы избавиться от отдельных объектов.

0 голосов
/ 18 октября 2011

finalize () - это средство для выполнения последнего бита кода непосредственно перед тем, как объект будет готов для сборки мусора (когда у объекта нет строгой ссылки на него).

Так, когда это должно использоваться? Только в настоящих двух случаях:

  1. В качестве обеспечения безопасности, чтобы убедиться, что некоторые службы закрыты или некоторые желаемое окончательное изменение сделано. Например, класс InputStream использует его закрыть поток ввода-вывода. Вот например ты сделал экземпляр BufferedInputStream. Вручную после его использования предположим закрыть () это. Но потому что можно забыть сделать это, finalize () действует как сеть безопасности для закрытия () потока.
  2. Несмотря на то, используя родные. Потому что сборщик мусора не имеет никакого контроля над родным объекты finalize () могут использоваться как средство для его восстановления.

Кроме двух вышеупомянутых случаев, никогда не используйте его. Чтобы понять почему? нам нужно понять функционирование и жизненный цикл объекта.

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

  1. При создании объекта 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 (), который закроет необходимые ресурсы или для окончательного журнала и т. Д. полный пост на нем . Я надеюсь, что это очищает.

...