uso titledborder poner example borde java methods garbage-collection call finalize

poner - titledborder java



¿Cuándo se llama el método finalize() en Java? (17)

¿Cuándo se llama el método finalize() en Java?

Se llamará al método de finalización después de que el GC detecte que el objeto ya no es accesible, y antes de que realmente reclame la memoria utilizada por el objeto.

  • Si un objeto nunca se vuelve inalcanzable, nunca se invocará finalize() .

  • Si el GC no se ejecuta, a continuación, finalize() nunca se puede llamar. (Normalmente, el GC solo se ejecuta cuando la JVM decide que es probable que haya suficiente basura para que valga la pena).

  • Puede tomar más de un ciclo de GC antes de que el GC determine que un objeto específico es inalcanzable. (Los GC de Java suelen ser recopiladores "generacionales" ...)

  • Una vez que el GC detecta que un objeto es inaccesible y finalizable, se coloca en una cola de finalización. La finalización suele ocurrir de forma asíncrona con el GC normal.

(La especificación JVM en realidad permite que una JVM nunca ejecute finalizadores ... siempre que no recupere el espacio utilizado por los objetos. Una JVM que se implementó de esta manera quedaría inutilizada / inutilizada, pero este comportamiento está "permitido" .)

El resultado es que no es prudente confiar en la finalización para hacer las cosas que deben hacerse en un marco de tiempo definido. Es una "mejor práctica" no usarlos en absoluto. Debería haber una manera mejor (es decir, más confiable) de hacer lo que sea que esté tratando de hacer en el método finalize() .

El único uso legítimo para la finalización es limpiar los recursos asociados con los objetos que se han perdido por el código de la aplicación. Incluso entonces, debe intentar escribir el código de la aplicación para que no pierda los objetos en primer lugar. (Por ejemplo, use Java 7+ try-with-resources para asegurarse de que siempre se llame a close() ...)

Creé una clase de prueba que escribe en un archivo cuando se llama al método finalize () al reemplazarlo. No se ejecuta. ¿Alguien puede decirme la razón por la que no se está ejecutando?

Es difícil decirlo, pero hay algunas posibilidades:

  • El objeto no es basura recolectada porque aún es accesible.
  • El objeto no se recolecta como basura porque el GC no se ejecuta antes de que finalice la prueba.
  • El GC encuentra el objeto y el GC lo coloca en la cola de finalización, pero la finalización no se completa antes de que finalice la prueba.

Necesito saber cuándo se llama al método finalize() en la JVM . Creé una clase de prueba que escribe en un archivo cuando se llama al método finalize() al reemplazarlo. No se ejecuta. ¿Alguien puede decirme la razón por la que no se está ejecutando?


Java permite que los objetos implementen un método llamado finalize () que podría llamarse.

El método finalize () se llama si el recolector de basura intenta recopilar el objeto.

Si el recolector de basura no se ejecuta, el método no se llama.

Si el recolector de basura no puede recoger el objeto e intenta ejecutarlo de nuevo, el método no se llama en la segunda vez.

En la práctica, es muy poco probable que lo uses en proyectos reales.

Solo ten en cuenta que es posible que no se llame y que definitivamente no se llamará dos veces. El método finalize () podría ejecutarse cero o una vez.

En el siguiente código, el método finalize () no produce resultados cuando lo ejecutamos, ya que el programa se cierra antes de que sea necesario ejecutar el recolector de basura.

Source


protected void finalize() throws Throwable {}

  • cada clase hereda el método finalize() de java.lang.Object
  • el recolector de basura llama el método cuando determina que no existen más referencias al objeto
  • El método de finalización de objetos no realiza acciones, pero puede ser anulado por cualquier clase
  • Normalmente, debería anularse para limpiar recursos que no sean de Java, es decir, cerrar un archivo
  • Si se anula la finalize() , es una buena práctica de programación usar una instrucción try-catch-finally y llamar siempre a super.finalize() . Esta es una medida de seguridad para garantizar que no se pierda inadvertidamente el cierre de un recurso utilizado por los objetos que llaman a la clase

    protected void finalize() throws Throwable { try { close(); // close open files } finally { super.finalize(); } }

  • cualquier excepción lanzada por finalize() durante la recolección de basura detiene la finalización pero se ignora de otra manera

  • finalize() nunca se ejecuta más de una vez en ningún objeto

citado de: http://www.janeg.ca/scjp/gc/finalize.html

También puedes consultar este artículo:


A veces, cuando se destruye, un objeto debe realizar una acción. Por ejemplo, si un objeto tiene un recurso que no es Java, como un identificador de archivo o una fuente, puede verificar que estos recursos se liberan antes de destruir un objeto. Para manejar tales situaciones, java ofrece un mecanismo llamado "finalización". Al finalizarlo, puede definir acciones específicas que ocurren cuando un objeto está a punto de eliminarse del recolector de basura. Para agregar un finalizador a una clase, simplemente defina el método finalize () . El tiempo de ejecución de Java llama a este método cuando se trata de eliminar un objeto de esa clase. Dentro del método de finalización () , especifica las acciones que se realizarán antes de destruir un objeto. El recolector de basura se busca periódicamente en los objetos que ya no se refieren a ningún estado de ejecución o indirectamente a cualquier otro objeto con referencia. Antes de liberar un activo, el tiempo de ejecución de Java llama al método finalize () en el objeto. El método finalize () tiene la siguiente forma general:

protected void finalize(){ // This is where the finalization code is entered }

Con la palabra clave protegida , se impide el acceso a finalize () por código fuera de su clase. Es importante entender que finalize () se llama justo antes de la recolección de basura. No se llama cuando un objeto abandona el ámbito, por ejemplo. Significa que no puede saber cuándo o si se ejecutará finalize () . Como resultado, el programa debe proporcionar otros medios para liberar recursos del sistema u otros recursos utilizados por el objeto. No debe confiar en finalize () para la ejecución normal del programa.


Clase donde anulamos el método de finalización.

public class TestClass { public TestClass() { System.out.println("constructor"); } public void display() { System.out.println("display"); } @Override public void finalize() { System.out.println("destructor"); } }

Las posibilidades de finalizar el método que se está llamando.

public class TestGarbageCollection { public static void main(String[] args) { while (true) { TestClass s = new TestClass(); s.display(); System.gc(); } } }

cuando la memoria está sobrecargada con objetos de volcado, el gc llamará método de finalización

ejecute y vea la consola, donde no encontrará que el método de finalización se llame con frecuencia, cuando la memoria se sobrecargue, se llamará al método de finalización.


Dado que existe una incertidumbre en el método de llamada de finalize () por parte de JVM (no estoy seguro de si finalize () se sobrescribe o no se ejecuta), para fines de estudio, la mejor manera de observar lo que sucede cuando se llama finalize () es obligue a la JVM a llamar a la recolección de basura mediante el comando System.gc() .

Específicamente, se llama a finalize () cuando un objeto ya no está en uso. Pero cuando intentamos llamarlo creando nuevos objetos, no hay certeza de su llamada. Entonces, con certeza, creamos un objeto null c que obviamente no tiene uso futuro, por lo tanto, vemos la llamada finalizada del objeto c .

Ejemplo

class Car { int maxspeed; Car() { maxspeed = 70; } protected void finalize() { // Originally finalize method does nothing, but here we override finalize() saying it to print some stmt // Calling of finalize is uncertain. Difficult to observe so we force JVM to call it by System.gc(); GarbageCollection System.out.println("Called finalize method in class Car..."); } } class Bike { int maxspeed; Bike() { maxspeed = 50; } protected void finalize() { System.out.println("Called finalize method in class Bike..."); } } class Example { public static void main(String args[]) { Car c = new Car(); c = null; // if c weren`t null JVM wouldn''t be certain it''s cleared or not, null means has no future use or no longer in use hence clears it Bike b = new Bike(); System.gc(); // should clear c, but not b for (b.maxspeed = 1; b.maxspeed <= 70; b.maxspeed++) { System.out.print("/t" + b.maxspeed); if (b.maxspeed > 50) { System.out.println("Over Speed. Pls slow down."); } } } }

Salida

Called finalize method in class Car... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51Over Speed. Pls slow down. 52Over Speed. Pls slow down. 53Over Speed. Pls slow down. 54Over Speed. Pls slow down. 55Over Speed. Pls slow down. 56Over Speed. Pls slow down. 57Over Speed. Pls slow down. 58Over Speed. Pls slow down. 59Over Speed. Pls slow down. 60Over Speed. Pls slow down. 61Over Speed. Pls slow down. 62Over Speed. Pls slow down. 63Over Speed. Pls slow down. 64Over Speed. Pls slow down. 65Over Speed. Pls slow down. 66Over Speed. Pls slow down. 67Over Speed. Pls slow down. 68Over Speed. Pls slow down. 69Over Speed. Pls slow down. 70Over Speed. Pls slow down.

Nota : incluso después de imprimir hasta 70 y después de que el objeto b no se está utilizando en el programa, existe la incertidumbre de que b no está borrado por JVM debido a que no se imprime el "Método de finalización de llamada en la clase Bici ...".


Echa un vistazo a Effective Java, página 2 de la edición 27. Artículo 7: Evitar los finalizadores

Los finalizadores son impredecibles, a menudo peligrosos y generalmente innecesarios. Nunca hagas nada crítico con el tiempo en un finalizador. Nunca dependa de un finalizador para actualizar el estado persistente crítico.

Para terminar un recurso, use try-finally en su lugar:

// try-finally block guarantees execution of termination method Foo foo = new Foo(...); try { // Do what must be done with foo ... } finally { foo.terminate(); // Explicit termination method }


El método finalize() Java no es un destructor y no debe utilizarse para manejar la lógica de la que depende su aplicación. La especificación de Java indica que no hay garantía de que se llame al método finalize durante el tiempo de vida de la aplicación.

Lo que probablemente quieres es una combinación de finally y un método de limpieza, como en:

MyClass myObj; try { myObj = new MyClass(); // ... } finally { if (null != myObj) { myObj.cleanup(); } }


El método de finalize se llama cuando un objeto está a punto de obtener la basura recolectada. Esto puede ocurrir en cualquier momento después de que se haya convertido en elegible para la recolección de basura.

Tenga en cuenta que es completamente posible que un objeto nunca se recoja la basura (y, por lo tanto, la finalize nunca se llama). Esto puede suceder cuando el objeto nunca se vuelve elegible para gc (porque es accesible durante toda la vida útil de la JVM) o cuando en realidad no se realiza ninguna recolección de basura entre el momento en que el objeto se convierte en elegible y el momento en que la JVM deja de ejecutarse (esto ocurre con frecuencia programas de prueba).

Hay formas de decirle a la JVM que ejecute finalize en objetos que aún no se han utilizado, pero tampoco es una buena idea usarlos (las garantías de ese método tampoco son muy sólidas).

Si confía en finalize para el correcto funcionamiento de su aplicación, entonces está haciendo algo mal. finalize solo debe usarse para la limpieza de recursos (generalmente no Java). Y eso es exactamente porque la JVM no garantiza que alguna vez se llame a la finalize de ningún objeto.


El recolector de basura lo llama en un objeto cuando la recolección de basura determina que no hay más referencias al objeto.

Una subclase anula el método de finalización para disponer de los recursos del sistema o para realizar otra limpieza.

El contrato general de finalización es que se invoca siempre y cuando la máquina virtual Java haya determinado que ya no hay ningún medio por el cual se pueda acceder a este objeto por ningún subproceso que aún no haya muerto, excepto como resultado de una acción realizada por la finalización de algún otro objeto o clase que está listo para ser finalizado.

El método de finalización puede realizar cualquier acción, incluido hacer que este objeto vuelva a estar disponible para otros subprocesos.

Sin embargo, el propósito habitual de finalizar es realizar acciones de limpieza antes de que el objeto se descarte irrevocablemente. Por ejemplo, el método de finalización para un objeto que representa una conexión de entrada / salida podría realizar transacciones de E / S explícitas para interrumpir la conexión antes de que el objeto se descarte permanentemente.

El lenguaje de programación Java no garantiza qué subproceso invocará el método de finalización para cualquier objeto dado. Sin embargo, se garantiza que el subproceso que invoca finalize no mantendrá ningún bloqueo de sincronización visible cuando se invoque finalize. Si el método finalize lanza una excepción no capturada, la excepción se ignora y la finalización de ese objeto termina.

Después de que se haya invocado el método de finalización para un objeto, no se realiza ninguna acción adicional hasta que la máquina virtual Java haya determinado de nuevo que ya no hay ningún medio por el cual se pueda acceder a este objeto por ningún hilo que aún no haya muerto, incluidas las posibles acciones. por otros objetos o clases que están listos para ser finalizados, en cuyo punto el objeto puede ser descartado.

El método de finalización nunca es invocado más de una vez por una máquina virtual Java para cualquier objeto dado.

Cualquier excepción lanzada por el método de finalización hace que la finalización de este objeto se detenga, pero de lo contrario se ignora.


En general, es mejor no confiar en finalize() para realizar cualquier limpieza, etc.

Según el Javadoc (que valdría la pena leer), es:

Llamado por el recolector de basura en un objeto cuando la recolección de basura determina que no hay más referencias al objeto.

Como Joachim señaló, esto nunca puede suceder en la vida de un programa si el objeto está siempre accesible.

Además, no se garantiza que el recolector de basura se ejecute en ningún momento específico. En general, lo que trato de decir es finalize() probablemente no sea el mejor método para usar en general, a menos que haya algo específico para lo que necesites.


Finalize imprimirá el conteo para la creación de la clase.

protected void finalize() throws Throwable { System.out.println("Run F" ); if ( checkedOut) System.out.println("Error: Checked out"); System.out.println("Class Create Count: " + classCreate); }

principal

while ( true) { Book novel=new Book(true); //System.out.println(novel.checkedOut); //Runtime.getRuntime().runFinalization(); novel.checkIn(); new Book(true); //System.runFinalization(); System.gc();

Como puedes ver. A continuación se muestra el código ejecutado por primera vez cuando el recuento de clases es 36.

C:/javaCode/firstClass>java TerminationCondition Run F Error: Checked out Class Create Count: 36 Run F Error: Checked out Class Create Count: 48 Run F


Habiendo luchado con los métodos del finalizador últimamente (para deshacerme de los grupos de conexiones durante las pruebas), debo decir que el finalizador carece de muchas cosas. Usando VisualVM para observar, así como usar referencias débiles para rastrear la interacción real, descubrí que las siguientes cosas son ciertas en un entorno Java 8 (Oracle JDK, Ubuntu 15):

  • Finalizar no se llama de inmediato. El Finalizador (parte GC) posee la referencia de forma individual.
  • El recolector de basura predeterminado agrupa los objetos inalcanzables.
  • Finalizar se llama de forma masiva señalando un detalle de implementación de que hay una cierta fase en que el recolector de basura libera los recursos.
  • Llamar a System.gc () a menudo no hace que los objetos se finalicen con mayor frecuencia, solo hace que el Finalizer se dé cuenta de que un objeto inalcanzable es más rápido
  • La creación de un volcado de subprocesos casi siempre provoca el disparo del finalizador debido a la alta sobrecarga del montón durante la ejecución del volcado del montón o algún otro mecanismo interno
  • Las costuras de finalización deben estar limitadas por los requisitos de memoria (liberar más memoria) o por la lista de objetos marcados para la finalización de un determinado límite interno. Por lo tanto, si tiene una gran cantidad de objetos que se están finalizando, la fase de finalización se activará con más frecuencia y más temprano en comparación con solo algunos
  • Hubo circunstancias en que System.gc () activó una finalización directamente, pero solo si la referencia era una vida local y corta. Esto podría estar relacionado con la generación.

Pensamiento final

El método de finalización no es confiable pero se puede usar para una sola cosa. Puede asegurarse de que un objeto se cerró o se desechó antes de recolectar la basura, lo que hace posible implementar una protección contra fallas si los objetos con un ciclo de vida más complejo que involucran una acción de final de vida se manejan correctamente. Esa es la única razón por la que puedo pensar que hace que valga la pena para anularla.


Intenta ejecutar este programa para una mejor comprensión.

public class FinalizeTest { static { System.out.println(Runtime.getRuntime().freeMemory()); } public void run() { System.out.println("run"); System.out.println(Runtime.getRuntime().freeMemory()); } protected void finalize() throws Throwable { System.out.println("finalize"); while(true) break; } public static void main(String[] args) { for (int i = 0 ; i < 500000 ; i++ ) { new FinalizeTest().run(); } } }


Un Objeto se convierte en elegible para la recolección de Basura o GC si no es accesible desde cualquier hilo en vivo o cualquier referencia estática, en otras palabras, puede decir que un objeto es elegible para la recolección de basura si todas sus referencias son nulas. Las dependencias cíclicas no se cuentan como referencia, por lo que si el Objeto A tiene una referencia del objeto B y el objeto B tiene una referencia del Objeto A y no tienen ninguna otra referencia activa, los Objetos A y B serán elegibles para la recolección de basura. Generalmente, un objeto se vuelve elegible para la recolección de basura en Java en los siguientes casos:

  1. Todas las referencias de ese objeto establecidas explícitamente en nulas, por ejemplo, object = null
  2. El objeto se crea dentro de un bloque y la referencia sale del alcance una vez que el control sale de ese bloque.
  3. El objeto primario establecido en nulo, si un objeto contiene la referencia de otro objeto y cuando establece la referencia nula del objeto contenedor, el objeto secundario o contenido se convierte automáticamente en elegible para la recolección de elementos no utilizados.
  4. Si un objeto solo tiene referencias en vivo a través de WeakHashMap, será elegible para la recolección de basura.

finalize() se llama justo antes de la recolección de basura. No se llama cuando un objeto sale de alcance. Esto significa que no puede saber cuándo o incluso si se ejecutará finalize() .

Ejemplo:

Si su programa finaliza antes de que se produzca el recolector de basura, entonces finalize() no se ejecutará. Por lo tanto, se debe utilizar como un procedimiento de respaldo para garantizar el manejo adecuado de otros recursos o para aplicaciones de uso especial, no como los medios que utiliza su programa en su funcionamiento normal.


el método de finalización no está garantizado. Este método se llama cuando el objeto es elegible para GC. Hay muchas situaciones donde los objetos pueden no ser recolectados en la basura.