2009-06-16 9 views
15

¿Qué ocurre si guarda una referencia al objeto actual durante la finalización de la llamada? Por ejemplo:Referencia al objeto durante la finalización

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

¿El objeto se recolectó o no? ¿Qué ocurre cuando intentas acceder al bar.REFERENCE más tarde?

+4

+1 porque es una buena pregunta, pero espero que esto sea solo un ejercicio intelectual. ;) –

+0

no se preocupe, fue :) –

Respuesta

11

El objeto no es basura. Esto se conoce como "resurrección de objetos".

Hay que tener cuidado con eso, una vez que el finalizador se llama el GC no llamará de nuevo, en algunos entornos como .NET se puede volver a registrar el finalizador pero no estoy seguro acerca de java

6

Este tipo de cosas es la razón por la que generalmente se desaconseja el uso de finalize().

+0

Finalize solo debe usarse para liberar referencias a recursos no administrados. El GC se encargará finalmente de todas las referencias administradas para usted. –

+6

No, finalize NO se debe usar para eso, porque se ejecuta en un momento posterior arbitrario, o no se ejecuta en absoluto. Los recursos no administrados deberían liberarse explícitamente en un bloque finally.En el mejor de los casos, finalize() puede ser un failsafe agregado. –

+1

... pero incluso como una falla a prueba de fallas, es muy problemático. Como no es determinista, convertirá una fuga de recursos reproducible en una fuga intermitente de recursos, que ocurre con menos frecuencia, pero es mucho más difícil de reproducir. He estado allí, hecho eso :-(. – sleske

1

El método finalize() se puede invocar explícitamente en la instancia foo, o puede ser invocado por el recolector de elementos no utilizados cuando intenta reclamar el almacenamiento ocupado por ese objeto.

Si bar es una instancia válida, establece el campo REFERENCE en la instancia foo. Desde el punto de vista del recolector de basura, esto aumenta el recuento de referencias de foo.

Si se produce una excepción en el interior del finalize() método (por ejemplo, tal como un NullPointerException debido a bar ser null), entonces el proceso de finalización simplemente termina.

N.B. Como otros han señalado ... su ejemplo definitivamente es algo que debe evitarse.

9

Si es absolutamente necesario resucitar a objetos, este JavaWorld artículo sugiere la creación de un nuevo caso en lugar de resucitar la instancia está terminando porque si la instancia está finalizando se puede elegir para volver simplemente será recogido (no será ejecutar el finalizador de nuevo).

0

Dado que Java es un lenguaje y plataforma seguros, la memoria no se libera. También asociado PhantomReference s no se pondrá en cola en su ReferenceQueue s. La VM solo llamará al finalize en un objeto una vez. Hay un buen diagrama de estado en la especificación de JVM.

Normalmente, si utiliza un finalizador, debe dejar la declaración como @Override protected void finalize() throws Throwable, para no molestar a la API. Mejor aún use un finalizador protegido, como en Effective Java 1st Ed.

Este truco particular llegó a los titulares (del San Jose Mercury, de todos modos) cuando un grupo en Princeton lo usó para construir un ClassLoader personalizado del código que no era de confianza. Aunque la especificación ha sido ligeramente ajustada (el constructor Object tiene que terminar ejecutando normalmente antes de que se pueda llamar al finalizador, especificado en J2SE 5.0, implementado en Java SE 6), este sigue siendo un área problemática. Si está diseñando una API, asegúrese de que las clases sensibles no puedan ser subclases y ahórrese mucho dolor.

Cuestiones relacionadas