Значение «Метод finalize никогда не вызывается JVM более одного раза для любого данного объекта».в случае воскресения объекта? - PullRequest
0 голосов
/ 14 октября 2018

Согласно Java Doc:

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

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

ИЛИ

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

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

1 Ответ

0 голосов
/ 13 декабря 2018

Согласно ernest_k. Это номер 2. Объект будет собирать мусор без вызова его метода finalize ().

Добавление примера кода для завершения этого ответа, который я создал для проверки.

import java.util.HashSet;
import java.util.Set;

class Immortal {

    // making it public and non-fianl to modify from outside
    public static Set<Immortal> immortals = new HashSet<>();

    @Override
    protected void finalize() throws Throwable {
        System.out.println("Running finalize for " + this);
        immortals.add(this); // Resurrect the object by creating a new reference
    }
}

public class ObjectResurrection {

    public static void callGC() {
        // call garbage collection
        System.gc();

        // wait for some time to give chance to run garbage collection thread
        try {
            Thread.sleep(10 * 1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Immortal immortal1 = new Immortal();
        Immortal immortal2 = new Immortal();

        // print objects when they are alive.
        System.out.println("immortal1 = " + immortal1);
        System.out.println("immortal2 = " + immortal2);

        // print immortal set
        System.out.println("immortal set = " + Immortal.immortals);

        // make all objects garbage collectable
        immortal1 = null;
        immortal2 = null;

        callGC();

        // now objects will be null
        System.out.println("immortal1 = " + immortal1);
        System.out.println("immortal2 = " + immortal2);

        // but stays in immortal set
        System.out.println("immortal set = " + Immortal.immortals);

        // remove all objects from immortal set, and make them again eligible for GC
        Immortal.immortals.clear();

        callGC();

        // again print the immortal set
        // this time set will be empty, and those 2 objects will be destroyed by Garbage
        // Collection,
        // but this time they will not call finalize, because it is already called
        // you can notice no output from finalize method in the output this time
        System.out.println("immortal set = " + Immortal.immortals);
    }

}

Вывод вышеуказанной программы (на моем компьютере):

immortal1 = effective.java.item7.finalizer6.Immortal@70dea4e
immortal2 = effective.java.item7.finalizer6.Immortal@5c647e05
immortal set = []
Running finalize for effective.java.item7.finalizer6.Immortal@5c647e05
Running finalize for effective.java.item7.finalizer6.Immortal@70dea4e
immortal1 = null
immortal2 = null
immortal set = [effective.java.item7.finalizer6.Immortal@5c647e05, effective.java.item7.finalizer6.Immortal@70dea4e]
immortal set = []
...