Почему финал не вызывается? - PullRequest
10 голосов
/ 17 октября 2011

У меня есть пара вопросов, касающихся сборщика мусора в java.

Q1. Насколько я понимаю, finalize () вызывается, когда объект выходит из области видимости, а JVM собирается собирать мусор.Я думал, что метод finalize () автоматически вызывается сборщиком мусора, но в этом случае он не работает.Какое объяснение?Почему я должен явно вызывать метод finalize ()?

public class MultipleConstruct {
    int x,y;    
    public MultipleConstruct(int x)
    {
        this.x= x;
        y=5;        
        System.out.println("ONE");
    }

    @Override
    protected void finalize() throws Throwable {
        // TODO Auto-generated method stub
        super.finalize();
        System.out.println("FINALIZED");
    }
    public static void main(String[] args) throws Throwable {
        MultipleConstruct construct = new MultipleConstruct(3);
    }
}

Q2.Кроме того, когда вызывается сборщик мусора?Я понимаю, что gc является потоком демона и вызывается JVM в зависимости от оставшегося размера кучи.Означает ли это, что JVM ожидает, пока программа использует пороговое ограничение ресурсов, и затем уведомляет gc о необходимости очистки мусорных объектов.

РЕДАКТИРОВАТЬ: Как gc разрешает круговые ссылки?

Ответы [ 4 ]

8 голосов
/ 17 октября 2011

Существует много методов для finalize (), которые, откровенно говоря, много писать, но вкратце:

Объект находится в завершенном состоянии, если он все еще недоступен после того, как был запущен его метод завершения, если таковой имеется. Завершенный объект ожидает освобождения. Обратите внимание, что реализация виртуальной машины управляет запуском финализатора. Вам почти всегда лучше проводить собственную очистку, чем полагаться на финализатор. Использование финализатора также может оставить критические ресурсы, которые не будут восстановлены в течение неопределенного периода времени.

В вашем случае причина, по которой он не печатается, заключается в том, что вы не знаете, когда поток финализатора вызовет метод finalize (). Происходит то, что программа завершает работу, прежде чем что-либо может быть напечатано. Чтобы проверить это: отредактируйте код внутри основного кода с помощью (ПРИМЕЧАНИЕ: это не является гарантией, и вы не должны полагаться на него, но все же оно печатает некоторое время)

for(int i =0;i<1000000;i++)
    {
        MultipleConstruct construct = new MultipleConstruct(3);
        construct = null;
    }

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

Для получения дополнительной информации посетите:

http://jatinpuri.com/?p=106

5 голосов
/ 17 октября 2011

q1) метод finalize вызывается, когда объект подвергается сборке мусора, поэтому, если GC не выполняется, ваш финализатор может не вызываться. Вам нужно вызвать super просто, чтобы сохранить поведение, обеспечиваемое реализацией Object.

q2) точный момент, когда выполняется GC, зависит от множества факторов, таких как: какая JVM вы используете, параметры настройки, количество свободной кучи и т. Д. Таким образом, он зависит не только от используемого порога кучи. Вы также можете запросить выполнение GC с помощью System.gc (), но у вас нет никаких гарантий относительно того, когда и когда он будет фактически выполнен. Вы можете найти некоторые подробности о настройке GC в http://java.sun.com/performance/reference/whitepapers/tuning.html

2 голосов
/ 17 октября 2011

его называют , в конце концов или нет

в основном GC сканирует кучу для всего недостижимого и запускает финализатор на тех (после чего ему нужно еще раз доказать, что он недоступен для освобождения)

однако GC может потребоваться некоторое время (фактически не определенное и фактически зависящее от поведения программы), чтобы найти его, поэтому на самом деле не следует полагаться на него при утилизации критических данных

edit: что касается циклических ссылок, он различает объекты с методом финализации и объекты без одного

для объекта, который должен быть освобожден (удален из основной памяти), он может быть недоступен никаким кодом (включая финализаторы, которые все еще должны быть запущены)

когда 2 объекта с финализаторами могут запускать финализаторы, GC произвольно выбирает один объект и запускает на нем финализатор, а затем он может запускать другой объект

обратите внимание, что финализатор может работать, в то время как поля объектов могут быть или не быть завершены уже

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

finalize () вызывается автоматически во время сборки мусора. Метод System.gc () принудительно вызывает сборщик мусора. но мы должны будем уничтожить объект раньше. Пример:

     public class Sample 
{
    public Sample()
    {
        System.out.println("Object created");
    }
    @Override
    public void finalize()
    {
        System.out.println("Object Destroyed");
    }
    public static void main(String args[])
    {
        Sample x=new Sample();
        Sample y=new Sample();

        x=null;
        y=null;

        System.gc();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...