Вызывает ли JVM/GC `finalize()` на выходе программы/потока?

PS: Я знаю, как правильно очищать, не зависимо от finalize().

Не гарантирует ли Java, что при выходе из программы будет выполнена сборка мусора?

например. скажем, я сохранил некоторые данные в кеше, а не сериализуя его часто, я также реализовал finalize() с надеждой, что если по какой-либо причине (кроме краха) моя программа выйдет изящно, тогда кеш будет записан в DB/file/some-storage моим кодом в методе finalize(). Но в соответствии с следующим небольшим экспериментом кажется, что JVM не очищает память "изящно", она просто выходит.

Спецификация Java (см. выход программы) говорит НИЧЕГО, как память /gc обрабатывается при выходе. Или я должен был смотреть на другой раздел спецификации?

Возьмем следующий пример (вывод в конце) с использованием 1.6.0.27 64 бит в Windows 7

public class Main {

        // just so GC might feel there is something to free..
    private int[] intarr = new int[10000];

    public static void main(String[] args) {
        System.out.println("entry");
        Main m = new Main();
        m.foo();
        m = new Main();
        // System.gc();
        m.foo();
        m = null;
        // System.gc();
        System.out.println("before System.exit(0);");
        System.exit(0);
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("finalize()");
        super.finalize();
    }

    public void foo() { System.out.println("foo()"); }
}

/*
 * Prints:
 * entry 
 * foo() 
 * foo() 
 * before System.exit(0);
 */

Варианты:

  • Если я раскомментирую любой System.gc(), тогда не вызывается finalize().
  • Если я раскомментирую как System.gc(), тогда finalize() вызывается дважды.
  • Вызывается ли System.exit() или нет, не действует ли вызов finalize() или нет.

Ответ 1

Нет, Java не гарантирует, что при выходе программы GC будет запускаться. Если вы хотите, чтобы операция для peform при выходе использовала метод Runtime.addShutdownHook. Прочитайте эту статью Sun о том, что говорит SPEC.

Спецификация платформы Java составляет очень мало promises о как сбор мусора действительно работает. Вот что такое Java Virtual Спецификация машины (JVMS) должна сказать об управлении памятью.

Куча создается при запуске виртуальной машины. Хранилище кучи для объекты возвращаются системой автоматического управления хранением (известный как сборщик мусора); объекты никогда явно не освобождаются. Виртуальная машина Java не предполагает определенного типа автоматического хранилища системы управления и технологии управления хранением в соответствии с требованиями системного разработчика .1 Хотя это может показаться запутанный, тот факт, что модель сбора мусора не является жесткой определенная на самом деле важна и полезна - жестко определенный мусор может быть невозможно реализовать на всех платформах. Точно так же это может исключать полезные оптимизации и производительность платформы в долгосрочной перспективе.

Хотя нет ни одного места, содержащего полное определение требуемое поведение сборщика мусора, большая часть модели GC неявно заданный через несколько разделов на языке Java Спецификация и JVMS. Хотя нет никаких гарантий относительно последовательный процесс, все совместимые виртуальные машины разделяют основные жизненного цикла объекта, описанного в этой главе.

Ответ 2

См. Runtime.runFinalizersOnExit(). Обратите внимание, что он устарел, и обратите внимание на остальную часть комментария. Я думаю, что вы можете законно заключить, что он по умолчанию отключен, но вы также должны отметить, что он может быть включен.