Ссылка на объект во время финализации - PullRequest
18 голосов
/ 16 июня 2009

Что произойдет, если вы сохраните ссылку на текущий объект во время завершающего вызова? Например:

class foo {
    ...
    public void finalize() {
        bar.REFERENCE = this;
    }
}

Является ли объект сборщиком мусора или нет? Что происходит, когда вы пытаетесь получить доступ к bar.REFERENCE позже?

Ответы [ 5 ]

12 голосов
/ 16 июня 2009

Объект не является сборщиком мусора. Это известно как «Воскрешение объекта».

Вы должны быть осторожны с этим, как только финализатор вызывается, gc не будет вызывать его снова, в некоторых средах, таких как .NET, вы можете перерегистрировать финализатор, но я не уверен насчет java

9 голосов
/ 16 июня 2009

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

6 голосов
/ 16 июня 2009

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

2 голосов
/ 17 июня 2009

Поскольку Java является безопасным языком и платформой, память не освобождается. Также связанные PhantomReference s не будут ставиться в очередь на их ReferenceQueue s. Виртуальная машина будет вызывать finalize только один раз. В спецификации JVM есть хорошая диаграмма состояний.

Обычно, если вы используете финализатор, вы должны оставить объявление как @Override protected void finalize() throws Throwable, чтобы не нарушать API. Еще лучше использовать защищенный финализатор, как в Effective Java 1st Ed.

Этот конкретный трюк попал в заголовки (во всяком случае, в Сан-Хосе, Меркурий), когда группа в Принстоне использовала его для создания пользовательского ClassLoader из ненадежного кода. Хотя спецификация была немного ужесточена (конструктор Object должен нормально завершиться, прежде чем можно будет вызывать финализатор - указанный в J2SE 5.0, реализованном в Java SE 6), это все еще остается проблемной областью. Если вы разрабатываете API, убедитесь, что чувствительные классы не могут быть подклассами, и избавьте себя от горя.

1 голос
/ 16 июня 2009

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

Если bar является допустимым экземпляром, для поля REFERENCE устанавливается значение foo. С точки зрения сборщика мусора, это увеличивает количество ссылок foo.

Если в методе finalize() генерируется исключение (например, например, NullPointerException из-за bar, являющегося null), то процесс завершения просто завершается.

N.B. Как уже отмечали другие ... ваш пример определенно стоит избегать.

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