funcion java finalize

funcion finalize en java



¿Por qué el método finalize() en java.lang.Object está "protegido"? (9)

Por curiosidad,

¿Por qué el modificador de acceso del método finalize() se realiza como protected ? ¿Por qué no puede ser public ? ¿Alguien puede explicarme alguna razón específica detrás de esto?

Además, llegué a saber que el método finalize() se llama solo una vez. Si lo llamo dos veces en mi programa internamente, ¿qué está pasando? ¿El recolector de basura lo llamará de nuevo?

private void dummyCall() { try { finalize(); finalize(); } catch (Throwable e) { e.printStackTrace();//NOT REACHES EXCEPTION } }


¿Por qué el modificador de acceso del método finalize () se realiza como protegido? ¿Por qué no puede ser público?

No es público porque no debe ser invocado por nadie más que la JVM. Sin embargo, debe estar protegido para que pueda ser anulado por subclases que necesiten definir un comportamiento para él.

Si lo llamo dos veces en mi programa, ¿qué está sucediendo internamente?

Puedes llamarlo todo lo que quieras, es solo un método después de todo. Sin embargo, al igual que public static void main(String [] args) , tiene un significado especial para JVM

¿El recolector de basura lo llamará de nuevo?


Además, llegué a saber que el método finalize () se llama solo una vez. Si lo llamo dos veces en mi programa, ¿qué está sucediendo internamente?

Probablemente preguntes esto bajo la impresión de C ++ ~ destructores. En el método java finalize () no se hace magia (como borrar la memoria). Se supone que debe ser llamado por el recolector de basura. Pero no al revés

Te recomiendo que leas el capítulo de corresponsal en "Java efectivo" de Joshua Bloch. Dice que usar finalizadores es una mala práctica y puede causar problemas de rendimiento y otros, y solo hay varios casos en los que deben usarse. El capítulo comienza con las siguientes palabras:

Los finalizadores son impredecibles, a menudo peligrosos y generalmente innecesarios.


Creo que la razón por la cual finalize está protegido sería que tal vez esté anulado por algunas clases en el JDK, y JVM llama a esos métodos anulados.


Echa un vistazo a este enlace que lo discute.

Básicamente, tendría más sentido que fuera private , ya que solo debería ser invocado por la JVM (recolector de basura). Pero para permitir que una subclase llame al método padre finalize() como parte de su finalize() , debe estar protected .

( Editar - Y solo una precaución general: el uso del método finalize () generalmente se desaconseja, ya que no hay forma de garantizar que alguna vez se llame. Aunque eso no significa que nunca tendrás ocasión de usarlo, es solo raro)


La parte acerca de que finalize() se invoque solo una vez se aplica solo a las llamadas del GC. Puede imaginarse que el objeto tiene un indicador oculto " finalize() fue llamado por el GC", y el GC verifica ese indicador para saber qué hacer con el objeto. La bandera no se ve afectada de ninguna manera por sus propias llamadas hechas a mano para finalize() .

Al finalizar, lea este artículo de Hans Boehm (que es conocido por su trabajo en la recolección de basura). Esto es una revelación sobre la finalización; en particular, Boehm explica por qué la finalización es necesariamente asincrónica. Un corolario es que, aunque la finalización es una herramienta poderosa, rara vez es la herramienta adecuada para un trabajo determinado.


No es public (o acceso predeterminado) porque debe ser invocado por la JVM internamente cuando el objeto es basura recolectada; no debe ser llamado por ninguna otra persona. Y no es private porque está destinado a ser anulado y no puede anular los métodos privados.

Si lo llamo dos veces en mi programa, ¿qué está sucediendo internamente? ¿El recolector de basura lo llamará de nuevo?

Probablemente sí, pero es difícil imaginar un escenario donde esto tenga algún sentido; el objetivo de finalize() es hacer una limpieza cuando un objeto es basura. Y ni siquiera funciona tan bien, así que es algo que debes evitar por completo en lugar de experimentar.


Respondo tu pregunta con otra pregunta:

¿Por qué el método de finalize no debería estar protegido?

En general, debes tratar de mantener todo lo más privado posible. De eso se trata la encapsulación. De lo contrario, podrías hacer que todo sea public . finalize no puede ser private (ya que las clases derivadas deberían poder acceder a él para poder anularlo), por lo que al menos debería estar protected pero ¿por qué dar más acceso cuando no es deseable?

Después de leer su comentario con más cuidado, creo que veo su punto principal ahora. Creo que su punto es que todo se deriva de java.lang.Object y consecuentemente accede a sus miembros protected , no haría ninguna diferencia para él (o cualquier método en java.lang.Object para ese asunto) ser public en oposición a protected Personalmente, consideraría esto como un defecto de diseño en Java. Esto está de hecho arreglado en C #. El problema no es por qué finalize está protegido. Está bien. El verdadero problema es que no debería poder llamar a los métodos protegidos en la clase base a través de una referencia de objeto del tipo de clase base. Eric Lippert tiene una entrada en el blog que explica por qué es tan malo permitir este tipo de acceso a los miembros protegidos que se desarrolla en Desbordamiento de pila en esta pregunta .


finalize () solo lo utiliza la JVM para limpiar recursos cuando se recopila el objeto. Es razonable que una clase defina qué acciones se deben tomar en la recopilación, para lo cual es posible que necesite acceder a super.finalize (). Realmente no tiene sentido que un proceso externo llame a finalize (), ya que un proceso externo no tiene control sobre cuándo se recopila el objeto.


  • finalize está destinado a ser llamado por el gc solamente y como tal no requiere acceso público
  • finalize está garantizado para ser llamado una sola vez por el gc , llamándolo usted mismo romperá esta garantía, ya que el gc no lo sabrá.
  • Cualquier clase superior puede hacer pública la finalización, lo cual creo que es malo por los motivos anteriores
  • finalize no debe contener mucho código, ya que cualquier excepción lanzada por finalize puede matar el hilo del finalizador del gc.

Rant contra finalize ()

  • Administrar recursos nativos o cualquier recurso que requiera disponer () o cerrar () para llamar puede causar errores difíciles de encontrar, ya que solo se liberarán cuando el archivo jvm se quede sin memoria, debe liberar recursos manualmente. Finalize solo debe usarse para depurar fugas de recursos o para casos en los que administrar recursos manualmente es demasiado trabajo.
  • finalizar se invocará en un subproceso adicional del gc y puede causar problemas con el bloqueo de recursos, etc.
  • las clases de referencia como WeakReference y ReferenceQueue son una forma alternativa (bastante compleja) de lidiar con la limpieza y pueden tener los mismos problemas que finalize () para los recursos nativos.

Tenga cuidado con los errores en las declaraciones anteriores, estoy un poco cansado :-)