Как метод finalize () работает в Java? [Дубликат]

Мне понравился ответ Powtac, но я хотел использовать его в Angular, поэтому я создал фильтр, используя его код.

.filter('HHMMSS', ['$filter', function ($filter) {
    return function (input, decimals) {
        var sec_num = parseInt(input, 10),
            decimal = parseFloat(input) - sec_num,
            hours   = Math.floor(sec_num / 3600),
            minutes = Math.floor((sec_num - (hours * 3600)) / 60),
            seconds = sec_num - (hours * 3600) - (minutes * 60);

        if (hours   < 10) {hours   = "0"+hours;}
        if (minutes < 10) {minutes = "0"+minutes;}
        if (seconds < 10) {seconds = "0"+seconds;}
        var time    = hours+':'+minutes+':'+seconds;
        if (decimals > 0) {
            time += '.' + $filter('number')(decimal, decimals).substr(2);
        }
        return time;
    };
}])

Это функционально идентично, за исключением того, что я добавил в поле дополнительных десятичных знаков для отображения дробных секунд. Используйте его, как и любой другой фильтр:

{{ elapsedTime | HHMMSS }} отображает: 01:23:45

{{ elapsedTime | HHMMSS : 3 }} отображает: 01:23:45.678

271
задан Vipin Jain 25 March 2016 в 06:46
поделиться

16 ответов

В общем, лучше не полагаться на finalize(), чтобы делать очистку и т. д.

Согласно Javadoc (что было бы полезно прочитать), это :

Вызывается сборщиком мусора на объекте, когда сбор мусора определяет, что больше нет ссылок на объект.

Как указал Йоахим, это может никогда не произойти в жизни программы, если объект всегда доступен.

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

232
ответ дан Paul Bellora 31 August 2018 в 17:22
поделиться

Иногда, когда он уничтожается, объект должен совершить действие. Например, если объект имеет не-java-ресурс, такой как дескриптор файла или шрифт, вы можете проверить, освобождены ли эти ресурсы до уничтожения объекта. Для управления такими ситуациями java предлагает механизм, называемый «финализация». Завершая его, вы можете определить конкретные действия, которые происходят, когда объект собирается быть удален из сборщика мусора. Чтобы добавить финализатор в класс, просто определите метод finalize (). Время выполнения Java вызывает этот метод всякий раз, когда он собирается удалить объект этого класса. В рамках метода finalize () вы указываете действия, которые необходимо выполнить перед уничтожением объекта. Сборщик мусора периодически ищет объекты, которые больше не ссылаются ни на какое рабочее состояние, ни косвенно на любой другой объект со ссылкой. Перед выпуском актива среда выполнения Java вызывает метод finalize () объекта. Метод finalize () имеет следующий общий вид:

protected void finalize(){
    // This is where the finalization code is entered
}

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

1
ответ дан Amarildo 31 August 2018 в 17:22
поделиться

метод finalize не гарантируется. Этот метод вызывается, когда объект становится подходящим для GC. Существует много ситуаций, когда объекты не могут быть собраны в мусор.

3
ответ дан Craig S. Anderson 31 August 2018 в 17:22
поделиться

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

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

Пример

class Car {

    int maxspeed;

    Car() {
        maxspeed = 70;
    }

    protected void finalize() {

    // Originally finalize method does nothing, but here we override finalize() saying it to print some stmt
    // Calling of finalize is uncertain. Difficult to observe so we force JVM to call it by System.gc(); GarbageCollection

        System.out.println("Called finalize method in class Car...");
    }
}

class Bike {

    int maxspeed;

    Bike() {
        maxspeed = 50;
    }

    protected void finalize() {
        System.out.println("Called finalize method in class Bike...");
    }
}

class Example {

    public static void main(String args[]) {
        Car c = new Car();
        c = null;    // if c weren`t null JVM wouldn't be certain it's cleared or not, null means has no future use or no longer in use hence clears it
        Bike b = new Bike();
        System.gc();    // should clear c, but not b
        for (b.maxspeed = 1; b.maxspeed <= 70; b.maxspeed++) {
            System.out.print("\t" + b.maxspeed);
            if (b.maxspeed > 50) {
                System.out.println("Over Speed. Pls slow down.");
            }
        }
    }
}

Выход

    Called finalize method in class Car...
            1       2       3       4       5       6       7       8       9
    10      11      12      13      14      15      16      17      18      19
    20      21      22      23      24      25      26      27      28      29
    30      31      32      33      34      35      36      37      38      39
    40      41      42      43      44      45      46      47      48      49
    50      51Over Speed. Pls slow down.
            52Over Speed. Pls slow down.
            53Over Speed. Pls slow down.
            54Over Speed. Pls slow down.
            55Over Speed. Pls slow down.
            56Over Speed. Pls slow down.
            57Over Speed. Pls slow down.
            58Over Speed. Pls slow down. 
            59Over Speed. Pls slow down.
            60Over Speed. Pls slow down.
            61Over Speed. Pls slow down.
            62Over Speed. Pls slow down.
            63Over Speed. Pls slow down.
            64Over Speed. Pls slow down.
            65Over Speed. Pls slow down.
            66Over Speed. Pls slow down.
            67Over Speed. Pls slow down.
            68Over Speed. Pls slow down.
            69Over Speed. Pls slow down.
            70Over Speed. Pls slow down.

Примечание. Даже после печати до 70 и после того, какой объект b не используется в программе, существует неопределенность в том, что b очищается или нет JVM, поскольку «Вызывается метод завершения в классе Bike ... "не печатается.

9
ответ дан cst1992 31 August 2018 в 17:22
поделиться

Объект становится пригодным для сбора мусора или GC, если его невозможно достичь из любых живых потоков или любых статических рефренсов, другими словами, вы можете сказать, что объект становится пригодным для сбора мусора, если все его ссылки равны нулю. Циклические зависимости не считаются ссылкой, поэтому, если объект А имеет ссылку на объект B, а объект B имеет ссылку на объект A, и у них нет другой живой ссылки, то оба объекта A и B будут иметь право на сбор мусора. Как правило, объект становится пригодным для сбора мусора в Java в следующих случаях:

  1. Все ссылки этого объекта явно установлены на нуль, например. object = null
  2. Объект создается внутри блока, а ссылка выходит из области действия после того, как элемент управления выйдет из этого блока.
  3. Родительский объект установлен в значение null, если объект имеет ссылку на другой объект и когда вы устанавливаете ссылочный нулевой объект контейнерного объекта, дочерний или содержащий объект автоматически становится подходящим для сбора мусора.
  4. Если у объекта есть только живые ссылки через WeakHashMap, он будет иметь право на сбор мусора.
2
ответ дан Darin Kolev 31 August 2018 в 17:22
поделиться

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

Пример:

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

0
ответ дан Fourat 31 August 2018 в 17:22
поделиться

Попробуйте запустить эту программу для лучшего понимания

public class FinalizeTest 
{       
    static {
        System.out.println(Runtime.getRuntime().freeMemory());
    }

    public void run() {
        System.out.println("run");
        System.out.println(Runtime.getRuntime().freeMemory());
    }

     protected void finalize() throws Throwable { 
         System.out.println("finalize");
         while(true)
             break;          
     }

     public static void main(String[] args) {
            for (int i = 0 ; i < 500000 ; i++ ) {
                    new FinalizeTest().run();
            }
     }
}
-3
ответ дан Fruchtzwerg 31 August 2018 в 17:22
поделиться

Java позволяет объектам реализовать метод finalize (), который может быть вызван.

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

Если сборщик мусора не запускается, метод не вызывается.

Если сборщик мусора не может собрать объект и пытается запустить его снова, метод не будет вызван в во второй раз.

На практике вы вряд ли сможете использовать его в реальных проектах.

Просто имейте в виду, что он не может быть вызван и что он определенно не будет дважды. Метод finalize () может начинаться с нуля или один раз.

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

Источник

0
ответ дан JavaDev 31 August 2018 в 17:22
поделиться
340
ответ дан Joachim Sauer 31 August 2018 в 17:22
поделиться

В последнее время борясь с методами финализатора (чтобы избавиться от пулов соединений во время тестирования), я должен сказать, что финализатору не хватает многих вещей. Используя VisualVM для наблюдения, а также используя слабые ссылки для отслеживания фактического взаимодействия, я обнаружил, что в среде Java 8 выполняются следующие вещи (Oracle JDK, Ubuntu 15):

  • Finalize не вызывается немедленно Finalizer (GC part) индивидуально владеет эталоном неуловимо
  • По умолчанию сборщики пулов Garbage собирают недостижимые объекты
  • Finalize вызывается в массе, указывая на деталь реализации, что есть определенная фаза мусора сборщик освобождает ресурсы.
  • Calling System.gc () часто не приводит к тому, что объекты будут финализироваться чаще, это просто приводит к тому, что Finalizer быстрее узнает о недоступном объекте
  • Создание дампа потока почти всегда приводит к запуску финализатора из-за высокой накладной кучи во время выполнения дампа кучи или какого-либо другого внутреннего механизма
  • Швы финализации должны быть связаны требованиями к памяти (освободите больше памяти) или список объектов, помеченных для финализации рост определенного внутреннего предела. Поэтому, если у вас есть много объектов, которые будут завершены, фаза завершения будет срабатывать чаще и раньше по сравнению с несколькими
  • . Были обстоятельства, при которых System.gc () запускает финализацию напрямую, но только если ссылка была местной и короткой жизнью. Это может быть связано с генерацией.

Final Thought

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

4
ответ дан Martin Kersten 31 August 2018 в 17:22
поделиться

Класс, где мы переопределяем метод finalize

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

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

Шансы на метод finalize, который вызывается

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

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

запустите и посмотрите консоль, где вы не часто вызываете метод finalize, когда память перегружается, тогда вызывается метод finalize.

1
ответ дан Meet Doshi 31 August 2018 в 17:22
поделиться

finalize будет распечатывать счетчик для создания класса.

protected void finalize() throws Throwable {
    System.out.println("Run F" );
    if ( checkedOut)
        System.out.println("Error: Checked out");
        System.out.println("Class Create Count: " + classCreate);
}

main

while ( true) {
    Book novel=new Book(true);
    //System.out.println(novel.checkedOut);
    //Runtime.getRuntime().runFinalization();
    novel.checkIn();
    new Book(true);
    //System.runFinalization();
    System.gc();

Как вы можете видеть. Следующий вывод показывает, что gc был выполнен в первый раз, когда число классов равно 36.

C:\javaCode\firstClass>java TerminationCondition
Run F
Error: Checked out
Class Create Count: 36
Run F
Error: Checked out
Class Create Count: 48
Run F
5
ответ дан OnaBai 31 August 2018 в 17:22
поделиться

Выйти Эффективная Java, страница 2-го издания 27. Пункт 7: Избегайте финализаторов

Финализаторы непредсказуемы, часто опасны и вообще не нужны. никогда не делайте ничего критически важного в финализаторе. никогда не зависеть от финализатора, чтобы обновить критическое постоянное состояние.

Чтобы завершить работу ресурса, вместо этого используйте try-finally:

// try-finally block guarantees execution of termination method
Foo foo = new Foo(...);
try {
    // Do what must be done with foo
    ...
} finally {
    foo.terminate(); // Explicit termination method
}
19
ответ дан rmtheis 31 August 2018 в 17:22
поделиться

Метод Java finalize() не является деструктором и не должен использоваться для обработки логики, от которой зависит ваше приложение. Спецификация Java заявляет, что нет гарантии, что метод finalize вызывается вообще во время жизни приложения.

То, что вы, вероятно, хотите, это комбинация finally и метода очистки, как в :

MyClass myObj;

try {
    myObj = new MyClass();

    // ...
} finally {

    if (null != myObj) {
        myObj.cleanup();
    }
}
21
ответ дан rsp 31 August 2018 в 17:22
поделиться

Когда метод finalize() вызывается в Java?

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

  • Если объект никогда не становится недоступным, finalize() никогда не будет вызываться на нем.
  • Если GC не запускается, finalize() никогда не может быть вызвана. (Обычно GC работает только тогда, когда JVM решает, что, вероятно, будет достаточно мусора, чтобы сделать его стоящим.)
  • Может потребоваться более одного цикла GC до того, как GC определит, что конкретный объект недоступен. (Java-GC, как правило, являются «генераторными» коллекторами ...)
  • Как только GC обнаруживает, что объект недоступен и финализирован, он помещается в очередь финализации.

(Фактическая спецификация JVM позволяет JVM в never запускать финализаторы ... при условии, что что он не восстанавливает пространство, используемое объектами. JVM, который был реализован таким образом, будет искалечен / бесполезен, но это поведение «разрешено».)

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

Единственное законное использование для финализации - очистка ресурсов, связанных с объектами, которые были потеряны кодом приложения. Даже тогда вы должны попытаться написать код приложения, чтобы он не потерял объекты в первую очередь. (Например, используйте Java 7+ try-with-resources , чтобы гарантировать, что close() всегда вызывается ...)


Я создал тест класс, который записывает в файл, когда метод finalize () вызывается путем его переопределения. Он не выполнен. Может ли кто-нибудь сказать мне причину, по которой он не выполняется?

Трудно сказать, но есть несколько возможностей:

  • Объект не
  • Объект не собирает мусор, потому что GC не запускается до завершения вашего теста.
  • Объект найден GC и помещен в завершение очереди GC, но до завершения теста завершение не завершено.
15
ответ дан Stephen C 31 August 2018 в 17:22
поделиться
protected void finalize() throws Throwable {}
  • каждый класс наследует метод finalize() из java.lang.Object
  • , метод вызывается сборщиком мусора, когда он не определяет больше ссылок на объект exist
  • Метод finalize объекта не выполняет никаких действий, но может быть переопределен любым классом
  • , как правило, он должен быть переопределен для очистки ресурсов, отличных от Java, т.е. закрытие файла
  • , если переопределить finalize(), хорошая практика программирования - использовать инструкцию try-catch-finally и всегда вызывать super.finalize(). Это мера безопасности, обеспечивающая непреднамеренное пропущение закрытия ресурса, используемого объектами, вызывающими класс
    protected void finalize() throws Throwable {
         try {
             close();        // close open files
         } finally {
             super.finalize();
         }
     }
    
  • . Любое исключение, созданное finalize() во время сбора мусора, останавливает завершение, но в противном случае игнорируется
  • finalize() никогда не запускается более одного раза на любом объекте

, указанном по адресу: http://www.janeg.ca/scjp/ gc / finalize.html

Вы также можете проверить эту статью:

66
ответ дан XpiritO 31 August 2018 в 17:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: